• ベストアンサー

文字操作(エンコード)について

基礎的な質問ですがよろしくお願いします。 <内容> WINDOWS2000のデスクトップ上のファイルを別のPCのWINDOWSにコピーするプログラム を考えています。シリアルケーブルを通じて。まずファイルネームを収得してから相手PCに送信し問題なければ続いてファイルの中身を送信します。 この際、ファイルの中身がバイナリなのかテキストなのか不定のためバイナリで送受信できるように InputStream、OutputStreamを使うことに決めました。 プログラムとしてはファイル名収得後 public void sendName(String fileName){ try{ //ポートへ出力 outputstream.write(fileName.getBytes()); }catch(Exception e){ System.err.println("ファイル名書き込み失敗"); } } 上記のプログラムで送信し、受信側は StringBuffer rb = new StringBuffer(); int nData = 0; try{ while((nData = inputstream.read()) != -1){ rb.append((char)nData); } String getName = new String(rb); }catch(IOException e){ System.err.println("ファイル名読み込み失敗"); } 上記のプログラムで受信しました。 <質問> 1.結果としては日本語が文字化けしたファイル名となりましたがどこが悪いのですか? 2.ファイルの中身の送受信も同じようなプログラムで行った(受け皿はFileoutputStreamですが)ところ、ファイルの中身はちゃんと日本語の部分は日本語で表示されていました。何か違いがあるのでしょうか? 3.もしInputStreamReader、InputStreamWriterを適用した場合、ファイルの中身を収得するときに 支障は出ませんか? 4.上記のような問題について勉強できるサイトがあれば教えてください。

  • Java
  • 回答数3
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • mojimojio
  • ベストアンサー率51% (14/27)
回答No.2

元のプログラムのStringBufferをByteArrayOutputStreamに置き換えて、以下のような感じでしょうか。 ByteArrayOutputStream baos = new ByteArrayOutputStream(); int nData = 0; try{ while((nData = inputstream.read()) != -1){ baos.write((byte)nData); } String getName = new String(baos.toByteArray()); : 実際、InputStreamから1バイトずつ読み込むのは効率的ではありません。InputStream#read(byte[])を使った方が良いでしょう。 今回のようにStringのやり取りでしたら、writeUTF, readUTFあたりを使った方が簡単です。 <送信側> DataOutputStream dos = new DataOutputStream(outputstream); dos.writeUTF(fileName); <受信側> DataInputStream din = new DataInputStream(inputstream); String getName = din.readUTF(); こんな感じで。

cyan1110
質問者

お礼

たいへん親切な回答ありがとうございました。いろんな手法が見れて勉強になりました。

その他の回答 (2)

  • hameggs
  • ベストアンサー率38% (8/21)
回答No.3

とりあえず、Servlet/JSPでの文字化けについての 参考サイトを載せて起きますヽ(´▽`)ノ

参考URL:
http://www.ingrid.org/java/jserv/i18n/corruptedchar.html
  • mojimojio
  • ベストアンサー率51% (14/27)
回答No.1

文字化けはエンコーディングの問題ではなくて、 > while((nData = inputstream.read()) != -1){ > rb.append((char)nData); > } ここがまずいです。 byteとcharは違います。送信側はbyte列として書き込んでいるので、受信側でもbyteの配列を読み込みましょう。(1と2の違いはこの辺りだと思います) Stringとbyte列の相互変換をするとき、使用する文字エンコーディングの指定ができるようになっています。(StringのコンストラクタやgetBytes) 指定しない場合はプラットフォームのデフォルトエンコーディングが使われます。 なので、Windows同士のやり取りには問題ありませんが、他プラットフォームとの通信がありえる場合には注意が必要です。 1) 文字ストリームとして扱う必要がある場合には、 InputStreamReader, OutputStreamWriterを使う。(コンストラクタで同じエンコーディングを指定する) 2) String単位でのやり取りで良い場合には、DataOutput#writeUTF, DataInput#readUTF などを使うのが便利。StringをwriteObjectするという方法もあります。

cyan1110
質問者

お礼

回答ありがとうございます。お手数ですが受信側でbyte配列の読み込みをしてString getNameに転送するまでの書き方を教えていただけないでしょうか?

関連するQ&A

  • テキストファイルからの読み込みについて

    度々の登場です。 外部テキストファイル内に ErrorMessage.txt ○○のエラーが発生しました △△のエラーが発生しました ■■のエラーが発生しました ・ ・ ・ ☆☆のエラーが発生しました --------------------------- と、そのプログラム内で発生する可能性のあるエラーメッセージを格納しておきます。 プログラム内で■■のエラーが発生したとします。 class Test{ public static void main(String[] args){ ・ ・ try{ ○○ }catch{ } try{ △△ }catch{ } try{ ■■ }catch{ } ・ ・ ・ try{ ☆☆ }catch{ } } } このとき 発生したエラーメッセージの内容をErrorMessage.txtから取得するにはどうしたらよいのですか? どうか、宜しくお願い致します。

    • ベストアンサー
    • Java
  • UTF-16LEにエンコード

    テキストファイル(ASCII)をUTF-16LEに文字コード変換するプログラムを作成したいのですが、 期待通りの結果がえられません。 下記のプログラムに問題があればご教授下さい。 (文字数の関係でコメント文を省略しました。) -------------------- StringsInputFile=args[0]; StringsOutputFile=args[1]; CharsetutfCharset=Charset.forName("UTF-16LE"); CharsetEncoderencoder=utfCharset.newEncoder(); ByteBufferutfBytes=null; try{ FileInputStreaminput=newFileInputStream(sInput); FileOutputStreamoutput=newFileOutputStream(sOutput); bytebuf[]=newbyte[256]; intlen; while((len=input.read(buf))!=-1){ ByteBufferunicodeBytes=ByteBuffer.wrap(buf); try{ utfBytes=encoder.encode(unicodeBytes.asCharBuffer()); } catch(CharacterCodingExceptione){ System.out.println("EncodeError!!["+e.getMessage()+"]"); continue; } output.write(utfBytes.array(),0,len); } output.flush(); output.close(); input.close(); }catch(FileNotFoundExceptione){ }catch(IOExceptione){ } return; } -------------------- 入力ファイルの中身は[TEST]と入力されています。 上記プログラムで得られた結果(出力ファイル) をバイナリエディタで確認すると 期待結果は [5400450053005400] なのですが、 [45545453](テキスト表示すると[ETTS]) となってしまいます。 できれば、BOM(FFFE)も先頭に付加したいです。 以上、宜しくお願い致します。

  • ソケット通信について

    自分はJAVAで、クライアント・サーバ形式の ネットワークゲームを作ろうとしているのですが、 チャットシステムで BufferedReader NetInput; // ネットワーク経由入力ストリーム PrintStream NetOutput; // ネットワーク経由出力ストリーム Socket socket; // ソケット ChatServer chatserver; // ChatServerオブジェクト int clientnumber; // クライアント番号 ChatClient(Socket socket, ChatServer chatserver, int clientnumber) { this.socket = socket; this.chatserver = chatserver; this.clientnumber = clientnumber; try { InputStream inputstream = socket.getInputStream( ); NetInput = new BufferedReader(new InputStreamReader(inputstream)); OutputStream outputstream = socket.getOutputStream( ); NetOutput = new PrintStream(outputstream); } catch(Exception e) { System.out.println("->" + e); } } // メッセージ送信 ------------------------ synchronized void sendMessage(String message) { NetOutput.println(message); // サーバからクライアントに送信 NetOutput.flush( ); } とString型の文字列messageを送受信し合う様に、 int型の配列や、boolean型の配列を送受信する方法があったら 教えていただきたいです。

  • Javaでのファイルアップ、ダウンロードについて

    Javaでのファイル(画像やテキストなど)の アップロードとダウンロードの仕組みについて、質問をさせていただきます。 上記を実現するにはストリームを利用することで実現可能であることを知りました。Javaの道具?としてinputstreamとoutputstreamがあります。 ストリームの仕組みについて、教えていただけないでしょうか。 以下は私の想定です。 ◇アップロードの場合 端末上でアップロードしたいファイルを用意すると、inputstreamがファイルをプログラム上(メモリ?)にデータをコピーします。そのあとoutputsreamでプログラム上にコピーしたデータをサーバー上にコピーする。 ◇ダウンロードの場合 サーバー上のファイルをinputstreamでプログラム上(メモリ?)にコピーして、outputstreamでプログラム上にコピーされたデータをローカルにコピーする。

  • 環境でeval()が利用できません

    3×3の簡易エクセルをjavaで作っているところです。 各セルにキーボードから入力された数値を表示するところまではできました。しかし、Data: と表示するところで、A1+A2などを入力すると、 エラーが出ます。 Row:A Line:1 Data:2 Row:A Line:2 Data:4 と入力しているとき Row:A Line:3 Data:A1+A2 と入力された際、 2 4 6 と表示させたいです。どう改良すればいいでしょうか? for(roop=0;roop<=8;roop++) { System.out.print("Row:"); try { Row_before = br.readLine(); } catch(IOException e) { System.err.println(e); } if(Row_before.equals("A")||Row_before.equals("B")||Row_before.equals("C")) { Row[roop] = Row_before;Row_before=""; } else {Row_before="";} System.out.print("Line:"); try { Line_before = br.readLine(); } catch(IOException e) { System.err.println(e); } if(Line_before.equals("1")||Line_before.equals("2")||Line_before.equals("3")) {Line[roop] = Line_before;Line_before="";} else {Line_before="";} System.out.println("Data:"); //A1に数値を入力 if(Row[roop].equals("A")&&Line[roop].equals("1")) { try { A1_string = br.readLine(); } catch(IOException e) { System.err.println(e); } A1 = Integer.parseInt(A1_string); System.out.println(""+A1_string); } //以下同様の動き if(Row[roop].equals("A")&&Line[roop].equals("2")) {try{A2_string = br.readLine();}catch(IOException e){System.err.println(e);}A2 = Integer.parseInt(A2_string);} if(Row[roop].equals("A")&&Line[roop].equals("3")) {try{A3_string = br.readLine();}catch(IOException e){System.err.println(e);}A3 = Integer.parseInt(A3_string);} if(Row[roop].equals("B")&&Line[roop].equals("1")) {try{B1_string = br.readLine();}catch(IOException e){System.err.println(e);}B1 = Integer.parseInt(B1_string);} if(Row[roop].equals("B")&&Line[roop].equals("2")) {try{B2_string = br.readLine();}catch(IOException e){System.err.println(e);}B2 = Integer.parseInt(B2_string);} if(Row[roop].equals("B")&&Line[roop].equals("3")) {try{B3_string = br.readLine();}catch(IOException e){System.err.println(e);}B3 = Integer.parseInt(B3_string);} if(Row[roop].equals("C")&&Line[roop].equals("1")) {try{C1_string = br.readLine();}catch(IOException e){System.err.println(e);}C1 = Integer.parseInt(C1_string);} if(Row[roop].equals("C")&&Line[roop].equals("2")) {try{C2_string = br.readLine();}catch(IOException e){System.err.println(e);}C2 = Integer.parseInt(C2_string);} if(Row[roop].equals("C")&&Line[roop].equals("3")) {try{C3_string = br.readLine();}catch(IOException e){System.err.println(e);}C3 = Integer.parseInt(C3_string);} System.out.println(""); }

  • 初歩的なソケット通信(java)

    初歩的なソケット通信(java) javaのソケット通信プログラムについて質問させて頂きます。まだまだ基礎の段階なのですが、詰まってしまたので、良かったら教えてください。 以下プログラムコード ------------------------------------- //サーバー側 import java.net.*; import java.io.*; public class Server { static int port = 12345; public static void main(String[] args) { try{ //サーバソケットの作成 ServerSocket ssoc = new ServerSocket(port); //メインループ while(true){ try{ System.out.println("クライアントからの接続を"+ port +"で待ちます"); Socket soc = ssoc.accept(); System.out.println(soc.getInetAddress().getHostName()+"から接続を受けました"); //処理をスレッドに任せます new Connect(soc); }catch(IOException e1){ e1.printStackTrace(); } } }catch(IOException e2){ e2.printStackTrace(); } } } class Connect extends Thread{ private Socket socket = null; public Connect(Socket socket){ this.socket = socket; //スレッド開始 this.start(); } public void run(){ try{ //出力ストリームを取得 OutputStream os = socket.getOutputStream(); PrintWriter out = new PrintWriter(os,true); //入力ストリームを取得 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader in = new BufferedReader(isr); String inputLine; while((inputLine = in.readLine()) != null){ //System.out.println(inputLine); out.println(inputLine); } System.out.println("処理が終わったので接続を切ります"); in.close(); out.close(); socket.close(); }catch(Exception e1){ try{ socket.close(); }catch(Exception e2){ e2.printStackTrace(); } } } }

  • ファイルまでのパス文字列からの変換について

    以下はJavaScriptからイメージファイルのパスを受け取り「\\」の部分を「/」に変換後 imageFile.exists()でそのファイルが存在するかを調べてからファイルを削除するものですが 結果がexists()の結果が「false」しか返ってきません。 しかしHTML側で戻り値「imageFilePath」の中身を見てみると「\\」の部分は「/」に変換されています。 また直接JavaScript側でremoveThumbnailImage()を呼び出す時に removeThumbnailImage("C:/Users/Admin/workspace/website/images/test.jpg")の様に直接パスを指定又はJava側でimageFilePath = "C:/Users/Admin/workspace/website/images/test.jpg"の様にするとexists()では「true」を返してきます。 どうすれば解決するでしょうか? public static String removeThumbnailImage(String imageFilePath){ //// 受け取ったパスの「\\」を「/」に変換するが「false」しか返ってこない //imageFilePath = imageFilePath.replaceAll("\\\\", "/"); ////以下の場合は「true」を返す(\\はバックスラッシュ2つ) //imageFilePath = "C:\\Users\\Admin\\workspace\\website\\images\\test.jpg"; //imageFilePath = "C:/Users/Admin/workspace/website/images/test.jpg"; //StringBuffer sb = new StringBuffer(); ////以下の処理でも結果は「false」 /*StringBuffer sb = new StringBuffer(); for(int i=0;i<imageFilePath.length();i++){ switch(imageFilePath.charAt(i)){ case '\\': sb.append("/"); break; default : sb.append(imageFilePath.charAt(i)); }//end switch }//end for*/ /////画像を保存したファイルまでのパスでFileオブジェクト生成 File imageFile = new File(sb.toString()); try{ ////イメージファイルが存在するか調べる if(imageFile.exists()){ ////イメージファイルを削除 //imageFile.delete(); return "true"; }else{ return imageFilePath; }//end if }catch(Exception e){ e.printStackTrace(); }//end try }

    • ベストアンサー
    • Java
  • javaプログラム初心者です。

    入力ファイルの内容をWebサーバプログラムへ送信し、サーバからの応答を別ファイルに出力するクライアントプログラムを作っているのですが、出力ファイルにはなにも書き込みがされていません。(サーバからの応答は事前に不明でその長さが可変長である) 以下が作ったプログラムです。間違っているところを詳しくご指摘いただけるとありがたいです。お願いします。 import java.net.*; import java.io.*; public class client{ static final int BUFSIZE = 1792; public static void main(String[] args){ try{ String server = args[0]; //接続先のIPアドレス File file1 = new File(args[1]); //入力ファイル(HTTPリクエスト) FileReader filereader = new FileReader(file1); BufferedReader br = new BufferedReader(filereader); int serverport = Integer.parseInt(args[2]); //ポート番号 File file2 = new File(args[3]); //サーバからの応答をファイルに書き込む用 FileWriter filewriter = new FileWriter(file2); BufferedWriter bw = new BufferedWriter(filewriter); byte[] bytebuffer = new byte[BUFSIZE]; String str; while((str = br.readLine()) != null){ //入力ファイルの内容を1行ずつ読み込む bytebuffer = str.getBytes(); //入力ファイルの文字列をバイトに変換 } Socket socket = new Socket(server,serverport); //ソケットの生成 System.out.println("Connected to server...sending echo string"); InputStream in = socket.getInputStream(); //入出力ストリームの取得 OutputStream out = socket.getOutputStream(); out.write(bytebuffer); //文字列を送信 int receive; while((receive = in.read(bytebuffer))!=-1){ bw.write(new String(bytebuffer)); //サーバからの応答をファイルに出力 } bw.close(); socket.close(); }catch(IOException e){ } } }

  • FileOutputStreamについて

    FileOutputStreamについて教えてください。 下記で行っている処理は入力ストリームからデータを受け取り、TEMPというファイルに 保存するというものです。たとえば入力ストリームから得るデータとしてはTEXTでA~Z まで書いたものだったとします。このデータは26バイトのデータです。よってwhile文を 2回実行して終わります。その後TEMPファイルを見るとYZというデータが入っているだけ でした。私の目的としてはA~Zまでファイルに書いてほしいのですがどうすればいいので しょうか?下記のfo = new FileOutputStream("TEMP",true);に変更して追加書き込みできる ようにしてみたらA~Zまで書いてくれるようになったのですが以前のデータが残っていると その続きから書いてしまいます。何かいい方法はないでしょうか? またfo.write(readBuffer,0,newData);の0の部分ですがこれはオフセットであると 書いてありますが、どういうときに使うものなのでしょうか? ***************************** byte[] readBuffer = new byte[20]; FileOutputStream fo; InputStream from_you; try{ fo = new FileOutputStream("TEMP"); }catch(IOException e){ System.err.println("例外" + e + "発生しました"); } try{ while(from_you.available() > 0){ nt newData = from_you.read(readBuffer); fo.write(readBuffer,0,newData); } fo.flush(); fo.close(); }catch(IOException e){ System.err.println("例外" + e + "発生しました"); }

    • ベストアンサー
    • Java
  • javaのsocket通信で20KB以上の文字列を

    javaのsocketについての質問です。サーバーとandroid端末で文字列のやりとりしています。 文字列は長いので、圧縮をかけ、android端末側で解凍を行っています。 そこで問題がおきました。文字データ量(20KB)が大きくなると、通信が完了せずに途中で止まってしまうのです。そこで文字列を分割(1KB毎)して送るなどを行い、しのいでおりましたが根本的の解決にはいたっていません。 InputStreamReader 、 BuffererdReader あたりを考えればいいと思うのですが、いまいち組み方がよくわからない状態です。 どなたか教えていただけないでしょうか? ============================= サーバー(PC側ソースコード)DataCompression は文字列を送って圧縮をかける独自のクラスです。 public class DataExchange extends Thread{ /* android端末とデータのやり取りをする */ private boolean DEBUG_FLAG = true; // private boolean DEBUG_FLAG = false; private InputStream is; private OutputStream os; private String sendStr; private String receiveStr; public DataExchange(InputStream is, OutputStream os, String sendStr) { this.is = is; this.os = os; this.sendStr = sendStr; } public void run() { //送信データ圧縮 DataCompression dc = new DataCompression(); byte[] sendByte = dc.getDataCompression(sendStr); //データ送信 try { os.write(sendByte); os.flush(); } catch (IOException e) { e.printStackTrace(); } if (DEBUG_FLAG) { System.out.println(os + " データ送信完了 = " + sendStr); } //データ受け取り byte[] buffer = new byte[1024]; try { int size = 0; while (size <= 0) { size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); } catch (IOException e) { e.printStackTrace(); } if (DEBUG_FLAG) { System.out.println(is + " データ受信完了 = " + receiveStr); } } public String getReceiveStr() { return receiveStr; } } ========================================= android端末側ソースコード public class DataExchange extends Thread{ /* android端末とデータのやり取りをする */ private InputStream is; private OutputStream os; private String sendStr; private String receiveStr; public DataExchange(InputStream is, OutputStream os, String sendStr) { this.is = is; this.os = os; this.sendStr = sendStr; } public void run() { //データ受け取り byte[] buffer = new byte[4096]; try { int size = 0; while (size <= 0) { size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); } catch (IOException e) { e.printStackTrace(); } /* 解凍 */ Inflater decompresser = new Inflater(); decompresser.setInput(buffer); int count; ByteArrayOutputStream decompos = new ByteArrayOutputStream(); while (!decompresser.finished()) { try { count = decompresser.inflate(buffer); decompos.write(buffer, 0, count); } catch (DataFormatException e) { e.printStackTrace(); } } receiveStr = decompos.toString(); System.out.println("データ受信完了 = " + receiveStr); //データ送信 try { byte[] sendByte = sendStr.getBytes("UTF8"); os.write(sendByte); os.flush(); } catch (IOException e) { e.printStackTrace(); } System.out.println("データ送信完了 = " + sendStr); } public String getReceiveStr() { return receiveStr; } }

    • ベストアンサー
    • Java

専門家に質問してみよう