質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

Q&A

解決済

4回答

3434閲覧

Javaでtxtファイル(ANSI)をUTF-8として取得したい。

lereve

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

0グッド

0クリップ

投稿2018/03/05 00:07

前提・実現したいこと

[前提]
趣味でプログラムを触ったことがある程度の初心者です。
今回、会社で初めてJavaを用いたPCソフトを作ることになりました。
質問内容はあまりに根本的な内容になるかとは思いますが、
参考本やHPに書かれている内容ではなかなか理解できず困っています。
是非、ご教授いただきたく思います。

[実現したいこと]
別のソフトからtxtファイル形式で出力されるデータを読み込み、
データベースに格納するといった処理を行いたいと思っています。

発生している課題・エラーメッセージ

[課題]
文字コードの変換方法がわかりません。
自己調査では.getByte()を使って行うのかなと思ったのですが、
格納後にチェックしてみると日本語が文字化けしてしまいます。

[その他情報]
・データベースやその他周辺のプログラムの文字コード指定は問題ないか
→txtファイルをUTF-8指定で保存、それをデータベースに格納すると問題なく表示されることから問題は今回のプログラムだと思っています。

そこで質問なのですが、
1.txtファイル(ANSI)をUTF-8で取得するにはどのような方法を用いれば良いのか。
(txtファイルは外部のプログラムからの出力なのでUTF-8指定で保存、は難しいと思っています。)
2..getbyte()を使う場合、https://www.sejuku.net/blog/19673 の内容を吟味しながら試してみたのですが、
byte[] bytes1 = str.getBytes("ANSI");
を行ってbyte型にしてから
String newStr1 = new String(bytes1, "UTF-8");
をすることでANSIの文字列がUTF-8に変換される、といった解釈で良いでしょうか。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

1.txtファイル(ANSI)をUTF-8で取得するにはどのような方法を用いれば良いのか。

y_waiwaiさん回答のように外部(テキストファイル)からJavaの世界(UTF16/UTF32)へ正しく読み込むと考えます。

ANSIの読み込みですが、Charset.forName("MS932")を用いるとよいと思います。"Shift_JIS"という文字セット名でも概ねうまくはいくのですが、それはMS932(Windows日本語版のMicrosoft独自Shift JIS)とは「厳密には違う文字セット」ですのでMS932を使うのが普通は無難と思います。メモ帳で見える文字と"Shift_JIS"で読み込んだ結果が不一致になるといったことが有り得ますので。

Java

1void boo() throws IOException { 2 try (InputStream is = new FileInputStream("xx"); 3 InputStreamReader isr = new InputStreamReader(is, Charset.forName("MS932")); 4 BufferedReader br = new BufferedReader(isr)) { 5 String line; 6 while ((line = br.readLine()) != null) { 7 // Javaとしての正しい文字列になっているはず 8 } 9 } 10}

2..getbyte()を使う場合

多くの場合getBytesで「UTF-8のバイト列を自分で生成」する必要はありません。ファイルなりDBなりへ文字列を出力する機能に「しかるべき文字セットを指定する方法」があるからです。

今のプログラムでも「DBへ期待通りの文字が格納できている」ケースがあるならば問題点は外部ファイル(MS932)からJava内部へ読み込むことだけと思います。

投稿2018/03/05 04:10

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lereve

2018/03/05 05:57

KSwordOfHaste様 たびたびお世話になります。 まさしく今回の質問の内容はKSwordOfHaste様がおっしゃる通りの内容でした。 「DBへ期待通りの文字が格納できている」という状況を読み解き、 言葉足らずな質問文から正確な回答を導いていただき、ありがとうございました。 新たな知識の獲得に繋がりました。 私も限られた情報から正確に問題点を見つけ出せるレベルになりたいです。 ありがとうございました。
guest

0

まず、ANSIというコードセットは英数字記号だけ(俗に言う1バイト文字)の文字コードです
ですので、日本語がある、という時点で、それはANSIではないので、なんの文字コードか、というのを調べる必要があります

で、何らかの文字コードからUFT8に変換する方法ですが、
「Java UTF8 変換」でぐぐるといろいろ解説が出てきますので、みてみてください。

-- 追記 --
元文字コードがShift-JISということでしたので、「Java SJIS UTF8」でぐぐってみました
その中で参考になりそうなところは、
https://dev.classmethod.jp/server-side/java/csv_read_java_char_trans/
まさにSJISのファイルをUTF8にして読み込んでますね

んで、気をつけないといけないところは、Java の標準の文字コードはUTF16だ、ということです
まず、ファイルの読み込みをShiftJISとして読み込む(ということはプログラム内部でUTF16で保存される)
そして、データベースに保存するときには、(UTF16から)UTF8に変換しなければいけない、ということですね

投稿2018/03/05 00:52

編集2018/03/05 02:10
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lereve

2018/03/05 01:54

y_waiwai様 ご回答ありがとうございます。 ANSIの件、「ほぉ…」というレベルでしかありませんがなんとなくわかりました。 txtファイルを[名前をつけて保存]する際にUTF-8などの文字コードを指定して保存できることから、 最初から選択肢がANSIだった為、今回のtxtファイルもANSIである、と勘違いしたようです。 ブラウザを用いて確認してみるとS-JISでありました。失礼しました。 そして肝心の変換の件ですが、私自身こういったサイトで質問させていただくのは 自分で半日調べてダメだったら…と決め事をしております。 その過程でもちろん「Java UTF8 変換」の検索も行っておりますが、理解には及びませんでした。 厚かましいお願いかとは思いますが、せめて参考のURLだけでもいただけないでしょうか。
KSwordOfHaste

2018/03/05 05:00 編集

横から失礼します。 > 英数字記号だけ(俗に言う1バイト文字)の文字コードです 多分それはASCIIコードのことをおっしゃっているのだと思います。じゃぁANSIって何のこと?なのかは自分にも謎ですが、その大元の意味は「米国国家規格協会。日本のJIS(日本工業規格)に相当」だろうと思います。少なくとも日本語Windowsにおいてはそれは「Microsoft独自ShiftJIS == Microsfot codepage 932」のことを意味するようです。 ---訂正--- https://en.wikipedia.org/wiki/ANSI_character_setをみて「ANSIにはASCIIコードをも意味する」と分かりました。自分の指摘ミスです。失礼しました。
fuzzball

2018/03/05 04:10 編集

ANSI ≒ シフトJISって思ってるのは日本人だけな気がします。 「少なくとも日本語Windowsにおいて」ということですね。
KSwordOfHaste

2018/03/05 04:16

> 日本語Windowsにおいて そのとおりです。DEFAULTとかせめてCP932とでも書いてくれた方がいい気がするのですが非プログラマーに対してCP932って書いてあってもわからないから別の用語にしてあるんでしょうか・・・ それにしてもANSIって書いてあっても「なにそれ」と思いませんか?w
otn

2018/03/05 04:21

> 多分それはASCIIコードのことをおっしゃっているのだと思います。 ANSIの文字コードと同じです。 ASCIIはANSIの前身のASAが定めた文字コードで、組織がANSIに変わったので今はANSCIIになっていますが、通称ASCIIです。
KSwordOfHaste

2018/03/05 04:59 編集

to: otnさん むむ、そうなんですか?だとすると日本語版WindowsでCP932で読み書きできるメモ帳がANSIと表記しているのは「間違い」なのでしょうか? --- 質問意図から離れたコメントになってしまってますね。スミマセン。 ---自己res--- https://en.wikipedia.org/wiki/ANSI_character_setをみました。 文字セットとしてのANSIは公式な意味はなく、いくぶん曖昧な使われ方をしており、「WindowsでISO-8859と概ね上位互換を持ついくつかのcodepageの集合を指すことが多い」ということのようでした。
otn

2018/03/05 05:22

> メモ帳がANSIと表記しているのは「間違い」なのでしょうか? 米語版はANSIでOKで、それを日本語版にローカライズする際の翻訳漏れでしょう。 > https://en.wikipedia.org/wiki/ANSI_character_setをみました。 そこの記述から推察されるのは、ヨーロッパ各国語版のWindowsメモ帳でも、保存ダイアログには、ISO-8859-1等 と書かれずにANSIと書いてあるということですね。ということで、MS的にはミスではなく意図的に記述をANSIに統一しているということかな。
KSwordOfHaste

2018/03/05 05:30

> MS的にはミスではなく意図的に記述をANSIに統一 自分もそう解釈しました。wikiみてようやく何を意図していそうかがわかった気がします。質問意図とちょっと外れた話してしまいすみませんでした。
lereve

2018/03/05 05:49

KSwordOfHaste様 fuzzball様 otn様 ご回答いただきありがとうございます。 内容のレベルに私の知識が追い付いておらず、ポカーンとなってしまいましたが確かにデータベースの設計をしている時はANSIではなくCP932を使いますね…日本語って難しい。という感じでした。 いずれにしろ知識の獲得へと繋がりました。 ありがとうございました。
lereve

2018/03/05 06:00

y_waiwai様 追記にてURLをいただきありがとうございました。 該当のページも流し読みしていたのですが、csvファイルであることから 「かんけーないわ」と思ってしまっていたようです。 文字コードの話ですから拡張子は何でも良かったですよね。 エラーと締切に追いかけられて目が回っていたようです。 大変参考になりました。 また、基礎を固めるいい機会になりました。 ありがとうございました。
guest

0

変換したいものがファイルである場合、javaのファイル入出力には文字コードを変換する機能がありますので、それを使います。

具体的にはnakazawaken1さんがコード記述されているので、ここでは省略します。

動作は次のようになります。

・ファイルから読むのと同時に、文字コード変換(シフトJis→javaの内部形式(UTF-16))して文字列として取得

・文字列(UTF-16)を文字コード変換(UTF-16→UTF-8)しながらファイルに書き出す


さて、質問者さんが調べた、

byte[] bytes1 = str.getBytes("ANSI");
String newStr1 = new String(bytes1, "UTF-8");

ですが、変換前後の文字列の使用をメモリ内だけで完結するようなケースで使います。
今回は、変換した文字列はファイルに書き出すだけなので、使用する必要はありません。
入出力処理の内部的に使っているので、あえて自分のプログラムでは使わなくてもいいと考えていいと思います。

それと、一応言っておくと、この2つの使い方が逆です。

byte[] bytes1 = str.getBytes("MS932");
文字列(内部コード)をMS932に変換したバイナリデータにする

String newStr1 = new String(bytes1, "UTF-8");
バイナリデータをUTF-8と判断して、文字列化(UTF-16)にする

という意味になりますので。

ちなみに、これらをどうしても使うなら、

1.テキストファイル(MS932)をバイナリデータとしてバイト配列(byte1)に読み込む
2.読み込んだbyte配列を、new String(bytes1, "MS932");で文字列化(str)する
3.文字列(str)をstr.getByte("UTF-8")でutf-8のバイト配列(byte2)に変換する
4.byte2をバイナリデータとしてファイルに出力する

となります。

「ファイルの入出力で行う」というのは、入力処理で1と2を、出力処理で3と4を同時に行っているということになります。

ちょっと、説明がグダグダになったような気もしますが、参考までに。

投稿2018/03/05 05:21

ngsvx

総合スコア287

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lereve

2018/03/05 06:05

ngsvx様 なるほど… byte[] bytes1 = str.getBytes("ANSI"); String newStr1 = new String(bytes1, "UTF-8"); の2行はメモリの中だけの処理になるのですね。 参照したURLはUTF16への変換についてのHPだった為、 処理の順番がおかしくなってしまったいたようです。 何気なく動かしているファイル入出力の中ではこんなことがおこっていたのですね。 また新たな知識を獲得することができました。 それぞれの行の詳細な動きも説明していただきありがとうございました。
guest

0

コードのサンプルを書いてみました。(java8)

java

1import java.io.IOException; 2import java.io.PrintWriter; 3import java.nio.charset.Charset; 4import java.nio.charset.StandardCharsets; 5import java.nio.file.Files; 6import java.nio.file.Path; 7import java.nio.file.Paths; 8import java.util.stream.Stream; 9 10/** 11 * Shift_JISのファイルをUTF-8に変換 12 */ 13public class Q116094 { 14 /** 15 * @param args 変換前ファイル、変換後ファイル 16 */ 17 public static void main(String[] args) { 18 if (args.length < 2) { 19 System.err.println("変換前ファイル、変換後ファイルを指定して実行してください "); 20 System.exit(1); 21 } 22 Path from = Paths.get(args[0]); // 変換前ファイル 23 if (!Files.exists(from)) { 24 System.err.println("変換前ファイルが見つかりません: " + from.toAbsolutePath()); 25 System.exit(2); 26 } 27 Path to = Paths.get(args[1]); // 変換後ファイル 28 try (Stream<String> lines = Files.lines(from, Charset.forName("MS932")); // Shift_JISで読込 29 PrintWriter writer = new PrintWriter(Files.newBufferedWriter(to, StandardCharsets.UTF_8))) { // UTF-8で出力 30 lines.forEach(writer::println); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35} 36

投稿2018/03/05 03:56

nakazawaken1

総合スコア94

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lereve

2018/03/05 05:52

nakazawaken1様 ご回答ありがとうございます。 まず、申し訳ありません。 私の質問が言葉足らずだった部分があり、誤解を招く形になっていたようです。 今回はtxtファイル(ANSI)から読み出し、UTF8でデータベースに格納する といった処理を考えていたので、ファイルの変換ではありませんでした。 しかしながらコードの書き方の部分で大変参考になりました。 私も綺麗なコードが書けるようになりたいものです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問