10

以下のコードで漢字を.txtファイルに保存しているのですが、ワードパッドで開いたら読めませんでした。

StringBuffer Shanghai_StrBuf = new StringBuffer("\u4E0A\u6D77");
boolean Append = true;

FileOutputStream fos;
fos = new FileOutputStream(FileName, Append);
for (int i = 0;i < Shanghai_StrBuf.length(); i++) {
    fos.write(Shanghai_StrBuf.charAt(i));
}
fos.close();

私に何ができる ?漢字をカット アンド ペーストしてワードパッドに貼り付ければ、.txt ファイルに保存できます。Javaでそれを行うにはどうすればよいですか?

4

5 に答える 5

10

ここでは、いくつかの要因が働いています。

  • テキスト ファイルには、エンコーディングを説明するための固有のメタデータがありません (山かっこ税の話ですが、XML が人気があるのには理由があります)。
  • Windows のデフォルトのエンコーディングは、値の範囲が限定された 8 ビット (または 2 バイト) の " ANSI " 文字セットのままです。この形式で記述されたテキスト ファイルは移植性がありません。
  • Unicode ファイルと ANSI ファイルを区別するために、Windows アプリはファイルの先頭にあるバイト オーダー マークの存在に依存しています (厳密にはそうではありません - Raymond Chen は説明しています)。理論的には、BOM はデータのエンディアン(バイト順) を示すために存在します。UTF-8 の場合、バイト オーダーは 1 つしかありませんが、Windows アプリはマーカー バイトに依存して、それが Unicode であることを自動的に判断します (ただし、メモ帳には、開く/保存するダイアログにエンコード オプションがあることに注意してください)。
  • Java は UTF-8 BOM を自動的に書き込まないため、Java が壊れていると言うのは誤りです。たとえば、Unix システムでは、BOM をスクリプト ファイルに書き込むとエラーになります。多くの Unix システムでは、デフォルトのエンコーディングとして UTF-8 が使用されます。既存のファイルにデータを追加する場合など、Windows でも不要な場合があります。fos = new FileOutputStream(FileName,Append);

UTF-8 データをファイルに確実に追加する方法を次に示します。

  private static void writeUtf8ToFile(File file, boolean append, String data)
      throws IOException {
    boolean skipBOM = append && file.isFile() && (file.length() > 0);
    Closer res = new Closer();
    try {
      OutputStream out = res.using(new FileOutputStream(file, append));
      Writer writer = res.using(new OutputStreamWriter(out, Charset
          .forName("UTF-8")));
      if (!skipBOM) {
        writer.write('\uFEFF');
      }
      writer.write(data);
    } finally {
      res.close();
    }
  }

使用法:

  public static void main(String[] args) throws IOException {
    String chinese = "\u4E0A\u6D77";
    boolean append = true;
    writeUtf8ToFile(new File("chinese.txt"), append, chinese);
  }

注: ファイルが既に存在し、追加することを選択し、既存のデータUTF-8 でエンコードされていない場合、コードが作成する唯一のものは混乱です。

Closerこのコードで使用される型は次のとおりです。

public class Closer implements Closeable {
  private Closeable closeable;

  public <T extends Closeable> T using(T t) {
    closeable = t;
    return t;
  }

  @Override public void close() throws IOException {
    if (closeable != null) {
      closeable.close();
    }
  }
}

このコードは、バイト オーダー マークに基づいてファイルを読み取る方法について、Windows スタイルの最良の推測を行います。

  private static final Charset[] UTF_ENCODINGS = { Charset.forName("UTF-8"),
      Charset.forName("UTF-16LE"), Charset.forName("UTF-16BE") };

  private static Charset getEncoding(InputStream in) throws IOException {
    charsetLoop: for (Charset encodings : UTF_ENCODINGS) {
      byte[] bom = "\uFEFF".getBytes(encodings);
      in.mark(bom.length);
      for (byte b : bom) {
        if ((0xFF & b) != in.read()) {
          in.reset();
          continue charsetLoop;
        }
      }
      return encodings;
    }
    return Charset.defaultCharset();
  }

  private static String readText(File file) throws IOException {
    Closer res = new Closer();
    try {
      InputStream in = res.using(new FileInputStream(file));
      InputStream bin = res.using(new BufferedInputStream(in));
      Reader reader = res.using(new InputStreamReader(bin, getEncoding(bin)));
      StringBuilder out = new StringBuilder();
      for (int ch = reader.read(); ch != -1; ch = reader.read())
        out.append((char) ch);
      return out.toString();
    } finally {
      res.close();
    }
  }

使用法:

  public static void main(String[] args) throws IOException {
    System.out.println(readText(new File("chinese.txt")));
  }

(System.out はデフォルトのエンコーディングを使用するため、意味のあるものを出力するかどうかは、プラットフォームと構成によって異なります。)

于 2009-04-20T10:14:02.207 に答える
4

デフォルトの文字エンコーディングが UTF-8 (またはその他の Unicode エンコーディング) であることが信頼できる場合は、次を使用できます。

    Writer w = new FileWriter("test.txt");
    w.append("上海");
    w.close();

最も安全な方法は、エンコーディングを常に明示的に指定することです。

    Writer w = new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8");
    w.append("上海");
    w.close();

PS javac の -encoding パラメータが正しく設定されていれば、メソッド名や変数名としても、Java ソース コードで任意の Unicode 文字を使用できます。これにより、ソース コードはエスケープされた形式よりも読みやすくなり\uXXXXます。

于 2009-04-19T23:34:02.150 に答える
1

多くの方法の中の 1 つの方法を次に示します。基本的には、バイトを FileOutputStream に出力する前に、変換を UTF-8 に行うように指定しているだけです。

String FileName = "output.txt";

StringBuffer Shanghai_StrBuf=new StringBuffer("\u4E0A\u6D77");
boolean Append=true;

Writer writer = new OutputStreamWriter(new FileOutputStream(FileName,Append), "UTF-8");
writer.write(Shanghai_StrBuf.toString(), 0, Shanghai_StrBuf.length());
writer.close();

http://www.fileformat.info/info/unicode/char/の画像に対してこれを手動で確認しました。今後は、小文字の変数名を含め、Java コーディング標準に従ってください。可読性が向上します。

于 2009-04-19T23:42:24.097 に答える
1

これを試して、

StringBuffer Shanghai_StrBuf=new StringBuffer("\u4E0A\u6D77");
    boolean Append=true;

    Writer out = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(FileName,Append), "UTF8"));
    for (int i=0;i<Shanghai_StrBuf.length();i++) out.write(Shanghai_StrBuf.charAt(i));
    out.close();
于 2009-04-20T00:01:20.213 に答える