FileOutputStreamについて

このQ&Aのポイント
  • FileOutputStreamとは、入力ストリームからデータを受け取り、指定のファイルに保存するためのクラスです。
  • fo = new FileOutputStream("TEMP",true)とすることで、既存のファイルに追加書き込みが可能ですが、以前のデータが残ってしまいます。
  • fo.write(readBuffer,0,newData)の0はオフセットを指定するもので、データの一部分から書き込みを行う場合に使用します。
回答を見る
  • ベストアンサー

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
  • 回答数6
  • ありがとう数7

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

  • ベストアンサー
  • sasadora
  • ベストアンサー率68% (59/86)
回答No.6

載せたソースは、EventListenerの方ですよね。 このEventをaddしている部分があると思うのですが、(または別のクラスでaddしている) それを複数回行っているとか。 addEventListenerを複数回行うと、イベントが発生したときに、 全部に通知されて、それがファイル書き込みを同時に行っている?? それか、いいかげんな答えなのかも知れませんが、シリアルポートの入出力ってそういうもんなんでしょうか? いっそsynchronizedで囲んじゃうとか。 ここまでくると、試してみないと分からないですね。

cyan1110
質問者

お礼

はい。ここまで相手していただいただけでもかなり勉強になりました。後は自分でいろいろ試して見ます。ありがとうございました。

その他の回答 (5)

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.5

やはりファイルへの書き込みが、同時に行われているということですね。 イベントで書き込みを処理を行っているそうですが、 どのイベントで書き込みをファイル書き込みを行いたいのでしょう? シリアルポートのイベントにどのようなものがあるかは、 分かっていないので、またしても想像なんですが…。(^^; イベントを受け取ったときに、どんなイベントかを判断して、 目的のイベントの時だけ処理を行い、それ以外は無視するように しないといけないのではないでしょうか? おそらく、入出力をしている間に様々なイベントが発生するのでしょう。 そのうち、必要なのは1つだけで、それ以外を無視するように しないといけないかと思います。 ちょっとだけcommunicationAPIを見てみたのですが、 SerialPortEventのgetEventType()を使って、目的のイベントの時だけ、 書き込みを行うとか。ちがうのかなぁ?

cyan1110
質問者

お礼

communicationAPIまで見ていただいてありがとうございます。現在は下記のようなプログラムになっています。なので他のイベントは弾いているつもりなんですが・・・ public void serialEvent(SerialPortEvent evt) { //データ収集処理 switch(evt.getEventType()){ case SerialPortEvent.DATA_AVAILABLE: byte[] readBuffer = new byte[20]; try{ File saveFile = new File("TEMP"); BufferedOutputStream fo = new BufferedOutputStream( new FileOutputStream(saveFile,true)); while(from_you.available() > 0){ int newData = from_you.read(readBuffer); fo.write(readBuffer,0,newData); System.out.print(new String(readBuffer)); } fo.flush(); fo.close(); newArrive = true; //新しいファイルの到着確認 }catch(IOException e){ System.err.println("例外" + e + "発生しました"); } break; case SerialPortEvent.BI: System.out.println("受信できません"); break; default: break; } }

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.4

関係なかったですか。お役に立てなくて申し訳ないです。 私もよく読んでなかったのですが、 ・ファイルに書き込まれる内容は、途中までではなく、最後のYZ ・標準出力に出力すると、A-Zまで正常に出力される だったのですね。 標準出力には出力されるのに、ファイルには書き込まれていないのは 不思議ですね。 1つのファイルに同時に書き込みが行われているということは、 ないんですよね?

cyan1110
質問者

お礼

十分参考にさせて頂いてます。ありがとうございます。どうもいろいろ見てみたのですが質問に書いた文はシリアルポートのEVENTメソッド内に記述しており、このEVENTが繰り返し呼ばれているようなふしがあります。標準出力は追記追記で書かれるので問題なく表示しているような気がします。しかし、ファイルのほうはEvent関数が呼ばれるたびに新しく作成しているので上書きしているような状態になっているような気がします。なぜ、このEVENT関数が何度も呼ばれてしまうのか分からないのです。

  • takaP-
  • ベストアンサー率79% (83/105)
回答No.3

>下記のfo = new FileOutputStream("TEMP",true); >に変更して追加書き込みできる ようにしてみたら >A~Zまで書いてくれるようになったのですが以前の >データが残っていると その続きから書いてしまいます。 >何かいい方法はないでしょうか? わたしもcommunicationAPIは知りませんので その部分については解答できませんが、とりあ えず、ファイルへの書きこみについてだけ。 出力用ファイルインスタンスを作成しdelete() メソッドで前のデータをファイルごと削除してし まってから新たにファイルに書き込むのはどうで しょうか? File file=new File("TEMP"); if(file.exists()) {   file.delete(); } FileOutputStream fo=new FileOutputStream(file,true); while(from_you.available() > 0) {   int newData=from_you.read(readBuffer);   fo.write(readBuffer,0,newData); }

cyan1110
質問者

お礼

ありがとうございます。期待の表示をするようになったのですがそれがなぜ かデバッガを実行して一つ一つデータを確かめながら実行しているときは 問題ないのですが、デバッガを実行せずに普通に実行するとファイルの 書き込みがYZだけになってしまいます。シリアルポートのタイミングが 関係しているような気がしています。もう少し自分で調べてみます。 ありがとうございました。

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.2

シリアルポートの入出力をやったことがないので、 どんな特性があるのか分かりませんが…。 シリアルポート側の出力がcloseされていないせいで、 最後まで読み込んだというのが分からないのでしょう。 closeせずに、読み込み側では更なる出力を待っている状態なんじゃないでしょうか? また読み込んだデータが足りないのは、シリアルポート側の出力が flushされていないせいだと思います。 想像でごめんなさい。

cyan1110
質問者

お礼

貴重なアドバイスありがとうございます。早速試してみました。相手のシリアルポートの出力をCLOSEしてみたのですが結果は変わらず-1では比較できませんでした。 flushの件についも結果に変化は見られませんでした。また、読み込んだデータはちゃんと受信側のPCに届いています。相手からA~Zまでを受信するとファイルに書き込まれるデータは最後のYZです。標準出力にも表示させているのですがちゃんとA~Zまで表示しています。 私の想像ですがシリアルポートに割り付けているリスナーのタイミングが変に検知しているのではないかと考え始めています。

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.1

InputStreamを実装しているのが何か分からないので、 自信ないのですが、 とりあえずavailableではなく、readで読み込んだバイト数が-1でないことを 確認してループしたらいいんではないでしょうか? readで読み込んだあと、実際に読み込んだバイト数が取得できます。 最後まで読み込んでもうデータがない場合には-1が返ります。 int len = 0; while((len = from_you.read(readBuffer) != -1){   fo.write(readBuffer, 0, len); } オフセットですが、これは何バイト目から書き込むか?という値です。 配列に「ABCDEFG」とあったときに、0バイト目からならば、 Aから。3バイト目からならDから。指定した長さ分書き込まれます。

cyan1110
質問者

お礼

入力ストリームのことですがfo= SerialPort.getInputStream()というのを使って、シリアルポートからデータを読んでいます。これはcommunicationAPIという所 からダウンロードしたものです。これが原因かどうか分かりませんが教えて頂いた int len = 0; while((len = from_you.read(readBuffer) != -1){   fo.write(readBuffer, 0, len); } で-1と比較させると応答がなくなります。でもavailableだとうまく動作します。ファイルなどの読み書きで-1を使うのはまったく問題ないのですが・・・ オフセットの使い方を教えていただきありがとうございました。

関連するQ&A

  • Return で文字列が返せない、、

    このような関数を作って、mainの関数に渡したいのですが、文法がダメだとコンパイラに怒られます。 private String test(){ try{ FileOutputStream fos=openFileOutput("sample.txt", MODE_PRIVATE); String text="サンプルテキストです"; fos.write(text.getBytes()); fos.close(); }catch(FileNotFoundException e){ }catch(IOException e){ } try{ FileInputStream fis=openFileInput("sample.txt"); byte buffer[]=new byte[100]; fis.read(buffer); String str = new String(buffer).trim(); fis.close(); return str; }catch(FileNotFoundException e){ }catch(IOException e){ } }なぜ返せないのでしょうか。

    • ベストアンサー
    • Java
  • try catchについて

    try catchの動きで質問があります。 以下が簡略化したソースです。 -------ここから--------------------- ストリーム1; ストリーム2; try{ try{ //ストリーム1を使った処理 }catch(IOException e){ throw e; }finally{ //ストリーム1のクローズ } try{ //ストリーム2を使った処理 }finally{ //ストリーム2のクローズ } } catch(IOException e){ throw new hogeException(); } ------ここまで-------------------------- 内側でスローされた例外は、外側でcatchされるのですか? また、内側でcatchをしなかった場合、外側でcatchされるのですか? この2点を教えていただきたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 環境で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(""); }

  • URLで指定したページのデータを読むには?

    URLをしていしてデータを読み込みたいのですが”java.net.ConnectException: Connection timed out”となってしまいます。なぜでしょうか。 import java.io.*; import java.net.*; /** * ウェブ上のデータを取得するサンプル * */ public class GetFileFromWeb { public static void main(String[] args){ URL url = null; //HttpURLConnection con = null; try{ //URLの指定 url = new URL("http://www.****"); //入力ストリームを取得する InputStream is = url.openStream(); //URLからデータを読み取り、表示する。 byte[] data = new byte[1024]; int i; while((i=is.read(data))!=-1){ System.out.write(data, 0, i); } }catch(MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • ストリームの問題について【至急】

    import java.io.*; public class FileStreamDemo { public static void main(String[] args){ try{ byte[] buffer=new byte[1024]; FileInputStream fileInputStream= new FileInputStream(new File(args[0])); FileOutputStream fileOutputStream= new FileOutputStream(new File(args[1])); System.out.println("コピーファイル: "+fileInputStream.available()+"バイト"); while(true){ if(fileInputStream.available()<1024){ int remain=-1; while((remain=fileInputStream.read())!=-1){ fileOutputStream.write(remain); } break; } else{ fileInputStream.read(buffer); fileOutputStream.write(buffer); } } fileInputStream.close(); fileOutputStream.close(); System.out.println("コピー完了"); } catch(ArrayIndexOutOfBoundsException e){ System.out.println( "using:java FileStreamDemo src des"); e.printStackTrace(); } catch(IOException e){ e.printStackTrace(); } } } JAVAの入門者です。 JAVAの教科書に書いてあるように、上のプログラムを書きましたけど… コンパイルすると、エラーメッセージが出て来ます。 エラー中身は下記のとおりです。 【using:java FileStreamDemo src des java.lang.ArrayIndexOutOfBoundsException: 0 at FileStreamDemo.main(FileStreamDemo.java:8) 】 どうすればいいのか悩んでいます。 誰か、助けていただけないのでしょうか?どこか間違ってるか、教えてください。 よろしく、お願いします。

  • Try-catch文(FileInputStream)

    下記コードでエラーが出現して困っています。 fis.close();の部分でコンパイルエラー( 変数 fis は初期化されていない可能性があります。)の結果が返ってきます。 必ず通過するfinallyブロックにclose()処理を記述して、この処理もエラーが発生する可能性があるので、try-catchする必要があると教師が言っていました。 エラーが出現する原因はなぜでしょうか? 回答のほどよろしくお願い致します。 FileInputStream fis; try{ fis = new FileInputStream(fi.getAbsolutePath()); while( (b[i++] = fis.read()) != -1); }catch(FileNotFoundException e){ } catch(IOException e){ }finally{ try{ fis.close(); ←コンパイルエラー( 変数 fis は初期化されていない可能性があります。) }catch(IOException e){ } }

    • ベストアンサー
    • Java
  • Java swing エクセル書き込み

    現在、poiで日報システムを作成しております。 入力されたデータはexcelに出力されるような処理をしました。 日報を入力し、ボタンを押されるたびに既存のexcelファイルに上書きされるようにしたいです。 もしエクセルが新規で出力される場合には1行目には見出しを、2行目には入力された内容が出力されます。 次にこのシステムを使った人が書き込みをした場合には3行目に内容が出力されるようにしていきたいです。 このためにexcelを読み込んで、空白セルを確認する処理をすればいいのでしょうが、試行錯誤しました、まず自分で保存先に空のExcelを作らないといけないということと、1回目の入力では正常に2行目まで出力されていますが、もう1度入力をし、出力をすると1,2行目が消えて3行目に書き込みがされるだけになってしまいます。 そこで2点ございます。 (1)2回目の出力で1,2行目が消えてしまうのはプログラムの組み方に誤りがあるのでしょうが、お手上げ状態です。 (2)excelが存在しない場合はこのシステム上で新たに作成をしてくれるようにもできるのでしょうか? ご教授いただければと思います。 public void ExcelOutput() { Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet(); /* * ファイルを読み込みし行数が「0」 * 何も書き込みがされていない場合にはヘッダと1つめの行(2行目)を書き込み */ if(ExcelInput() == 0){ Row head = sheet.createRow(0); Cell head1 = head.createCell(0); Cell head2 = head.createCell(1); head1.setCellValue("会社"); head2.setCellValue("報告者"); CellStyle styleHead = wb.createCellStyle(); styleHead.setFillPattern(CellStyle.SOLID_FOREGROUND); styleHead.setFillForegroundColor(IndexedColors.RED.getIndex()); head1.setCellStyle(styleHead); head2.setCellStyle(styleHead); Row contents = sheet.createRow(1); Cell contents1 = contents.createCell(0); Cell contents2 = contents.createCell(1); contents1.setCellValue(CompanyInput.getText()); contents2.setCellValue(NameInput.getText()); FileOutputStream out = null; try{ out = new FileOutputStream("ccc.xls"); wb.write(out); }catch(IOException e){ //System.out.println(e.toString()); }finally{ try { out.close(); }catch(IOException e){ //System.out.println(e.toString()); } } } /* * すでにエクセル作成済み(1,2行目に入力がされている)場合 * 途中から書き込み */ else{ Row contents = sheet.createRow(CompanyExcelInput()); Cell contents1 = contents.createCell(0); Cell contents2 = contents.createCell(1); contents1.setCellValue(InterviewPersonInput.getText()); contents2.setCellValue(NameInput.getText()); FileOutputStream out = null; try{ out = new FileOutputStream("ccc.xls"); wb.write(out); }catch(IOException e){ //System.out.println(e.toString()); }finally{ try { out.close(); }catch(IOException e){ //System.out.println(e.toString()); } } } } public int ExcelInput(){ int rowNullCount = 0; try{ //Excelのワークブックを読み込む POIFSFileSystem filein = new POIFSFileSystem (new FileInputStream("ccc.xls")); HSSFWorkbook wb = new HSSFWorkbook(filein); //シートを読み込む HSSFSheet sheet = wb.getSheetAt(0); //空行を検索し、空行を保持する for(rowNullCount = 0; rowNullCount <= sheet.getLastRowNum(); rowNullCount++) { HSSFRow row = sheet.getRow(rowNullCount); if(row == null){ break; } } } catch(IOException ioe) { // TODO } return rowNullCount; } ExcelInputとExcelOutputはボタンのactionPerformedで読み込んでいます。 宜しくお願い致します。

    • ベストアンサー
    • Java
  • Ajax は NN でも使えますか?

    初歩的な質問ですみません。 Ajax の非同期通信で、XMLHTTP オブジェクトを作成するスクリプトを見ると、 function createXMLHttpRequest() { var XMLhttpObject = null; try{ XMLhttpObject = new XMLHttpRequest(); }catch(e){ try{ XMLhttpObject = new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ try{ XMLhttpObject = new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){ return null; } } } return XMLhttpObject; } のように Microsoft のオブジェクトを読み込んでいるように見えるのですが、NN でもつかえるのでしょうか。 また、Macintosh との互換性はどうなのでしょうか。 ご存知の方はお教えください。

  • JPEG画像の書き出し

    JPEG画像を読み込んで別ファイルに出力するという操作を行いたくて、以下のように書きました。 //画像情報の取得 try { FileInputStream fis = new FileInputStream(fileName); JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fis); image = decoder.decodeAsBufferedImage(); fis.close(); } catch (IOException e) { System.err.println("Can't open the file."); } //** 中略 **// //画像情報の出力 try{ FileOutputStream fos = new FileOutputStream(fileName); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image); param.setQuality((float)1.0, false); encoder.setJPEGEncodeParam(param); encoder.encode(image); fos.close(); } catch (IOException e){ System.out.println("Can't save the new file."); } これで、実際に入出力はできるのですが、圧縮されるのかオリジナルとは違うものが出力されてしまいます。 コピーではなく、画素値の変更が一切ないように出力したい場合はどうしたらいいでしょうか?

    • ベストアンサー
    • Java
  • doPost+doGet

    public class Class{ public void doPost (HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException try{ //処理 }catch(Exception e){ e.printStackTrace(); } } public void doGet (HttpServletRequest request,HttpServletResponse response){ try{ doPost(request, response); }catch(Exception e){ e.printStackTrace(); } } } この処理は、doGetで送信されたものをdoPostに送って処理するということでよろしいのでしょうか? 分かる方がいましたら、よろしくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう