2016-08-05 1 views
0

소켓에서 바이트를 읽고 jsonGenerator를 사용하여 json 파일에 쓰고 있습니다. 문제는 JsonGenerator가 소켓에서 스트림을받을 때마다 파일을 덮어 쓰는 것입니다. 덮어 쓰기 대신 후속 스트림을 추가하려면 어떻게해야합니까? 또한jsonGenerator는 ovewriting없이 파일에 json 데이터를 추가합니다.

JsonFactory factory = new JsonFactory(); 
     JsonGenerator generator = factory.createGenerator(
      new File("transactions.json"), JsonEncoding.UTF8); 

      try { 
     while ((bytesRead = in.read(bytes)) != -1){ // -1 indicates EOF 

      output= new String(bytes, "UTF-8"); 
      String length = output.substring(0, 4).trim(); 
      String mti = output.substring(4, 8).trim(); 
      String resp = "000"; 
      String newoutput = ""; 
      String bitmap = output.substring(8, 24); 
      String stan = output.substring(24, 30); 
      String date = output.substring(30, 44); 
      String function_code = output.substring(44, 47); 
      mti = "1814"; 


       // output to file 

      generator.writeStartObject(); 
      generator.writeStringField("MTI", mti); 
      generator.writeStringField("lenght", length); 
      generator.writeStringField("stan", stan); 
      generator.writeStringField("date", date); 
      generator.writeStringField("Function Code", function_code); 
       generator.writeEndObject(); 
      } 
    } catch (Exception e) { 
       System.out.println("Exceptions "+e); 
      }finally{ 
       generator.close(); 

      } 

나는 while 루프 외부에서 발전기를 선언하고 데이터 그래서 당신이 종료 때 그것을 쓰는 버퍼처럼 좀 발전기를 가정하고 파일에 기록되지 않습니다 어떤 이유로 루프 외부를 닫을 때 파일.

+0

여러 개체를 쓰는 경우 배열이됩니다 –

+0

전체 메시지를 읽어야한다는 것을 알고 계십니까? 이 코드에서는 메시지의 절반을 읽고 처리하려고 시도 할 것이므로 예외가 발생할 수 있습니다. 소켓에서 inputStream의 청크를 읽고 하프로드가 아닌 전체 청크 만 처리하는 프로토콜이 있어야합니다. –

+0

Java 1.7을 사용하는 경우에는 finally 블록에서 생성기를 닫거나 "try-with-resources"에서 사용해야합니다. –

답변

1

나는 당신의 질문에서 뭔가를 놓칠지도 모르지만, 나에게 뛰어 드는 겹쳐 쓰기 이유는 파일을 첨부해야한다고 지정하지 않았다는 것입니다. 대부분의 Java API (Jackson 포함)는 기본적으로 추가하는 대신 덮어 씁니다. 이에 대한 간단한 해결책은 사용하는 단지입니다 :

// the second parameter specifies whether the file should be appended 
try(OutputStream fos = new FileOutputStream(new File("transactions.json"), true)) { 

    // pass the FileOutputStream to the generator instead 
    JsonGenerator generator = factory.createGenerator(fos , JsonEncoding.UTF8); 
} 

내 대답을 그 그것을 떠날 것이다,하지만 난 당신이 동시에 여러 소켓에서 읽고 있다면, 그때 지적하지 않은 경우 내가 놓칠 것 아마도 JSON 데이터가 인터리브되어 작성 될 것입니다.

이 문제를 방지하고 스레드로부터 안전하도록 일종의 동기화 블록에 메서드를 래핑하는 것이 좋습니다.

아래에는이 기능을 다시 쓰는 예제가 있습니다.

import com.fasterxml.jackson.core.JsonEncoding; 
import com.fasterxml.jackson.core.JsonFactory; 
import com.fasterxml.jackson.core.JsonGenerator; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.nio.charset.StandardCharsets; 

/** 
* A thread-safe class that will append JSON transaction data to a file. 
*/ 
public class TransactionWriter { 
    private static final JsonFactory jsonFactory = new JsonFactory(); 

    /** 
    * Helper method that will read a number of UTF8 characters from an input stream and return them in a string. 
    * 
    * @param inputStream stream to read from 
    * @param charsToRead number of characters to read 
    * @return string of read characters 
    * @throws IOException when unable to read enough characters from the stream 
    */ 
    private static String readUtf8Chars(InputStream inputStream, int charsToRead) throws IOException { 
     // since we know this is UTF8 up front, we can assume one byte per char 
     byte[] buffer = new byte[charsToRead]; 

     // fill the buffer 
     int readBytes = inputStream.read(buffer); 

     // check that the buffer was actually filled 
     if(readBytes < charsToRead) 
      throw new IOException("less bytes available to read than expected: " + readBytes + " instead of " + charsToRead); 

     // create a string from the buffer 
     return new String(buffer, StandardCharsets.UTF_8); 
    } 


    private final File file; 
    private final Object writeLock = new Object(); 

    /** 
    * Constructs a new instance for an output file. 
    * 
    * @param file file to append to 
    */ 
    public TransactionWriter(File file) { 
     this.file = file; 
    } 

    /** 
    * Reads a transaction from the input stream and appends a JSON representation to this instance's output file. 
    * 
    * @param inputStream stream to read from; will be closed after this method is closed 
    * @throws IOException when reading or writing failed 
    */ 
    public void write(InputStream inputStream) throws IOException { 
     // since we have multiple threads appending to the same file, synchronize to prevent concurrency issues 
     synchronized(writeLock) { 

      // open the output stream to append to the file 
      try(FileOutputStream outputStream = new FileOutputStream(file, true)) { 

       // create the generator for the output stream 
       JsonGenerator generator = jsonFactory.createGenerator(outputStream, JsonEncoding.UTF8); 

       // write the data to the generator 
       generator.writeStartObject(); 
       generator.writeStringField("length", readUtf8Chars(inputStream, 4).trim()); 
       generator.writeStringField("MTI", readUtf8Chars(inputStream, 4).trim()); 
       String bitmap = readUtf8Chars(inputStream, 16); 
       generator.writeStringField("stan", readUtf8Chars(inputStream, 8)); 
       generator.writeStringField("date", readUtf8Chars(inputStream, 14)); 
       generator.writeStringField("Function Code", readUtf8Chars(inputStream, 3)); 
       generator.writeEndObject(); 

      } finally { 
       // output stream is closed in try-with-resources, but also close the input stream 
       inputStream.close(); 
      } 
     } 
    } 
} 

명확하게하기 위해, 나는 모든이 코드를 테스트하지 않았습니다. Java 7 언어 수준에서 컴파일된다는 것을 알고 있습니다.

+0

. 너의 선택권을 시험하게하십시오.하지만 하나의 소켓에서 읽는 중입니다. 또한 여기서는 전체 코드를 넣지 않겠습니다. 스트림이 새로운 스레드를 생성 할 때 스레드를 사용하고 생성 된 후 실행합니다. 하지만 난 마침내 내가 작업자 스레드가됩니다 다중 스레드 서버와 그것을 수정합니다. 지금은 논리가 올바르게 작동하기를 바랍니다. –

0

루프 외부에 생성기를 선언하십시오 (루프 이전). 당신은 finally 블록 (루프 후) 발전기를 종료하거나 java 1.7

을 사용하는 경우 "try-with-resources"방법으로 그것을 사용해야

:

try-catch 문에서 루프를 가지고, 두 가지 옵션이 있습니다 또한 전체 메시지를 읽어야한다는 것을 알고 계십니까? 이 코드에서는 메시지의 절반을 읽고 처리하려고 시도 할 것이므로 예외가 발생할 수 있습니다. 소켓에서 inputStream의 메시지를 읽고 하프로드 된 덩어리가 아닌 전체 메시지 만 처리하는 프로토콜이 있어야합니다. - Krzysztof Cichocki 2 분 전 편집

+0

나는 당신의 아이디어를 시도했지만 여전히 파일에 아무 것도 쓰지 않고 작동하지 않는다. generator.close가 루프 밖으로 빠져 나온다. –

+0

새로운 코드를 게시 –

+0

새로운 코드가 올라 갔다. –

관련 문제