나는 당신의 질문에서 뭔가를 놓칠지도 모르지만, 나에게 뛰어 드는 겹쳐 쓰기 이유는 파일을 첨부해야한다고 지정하지 않았다는 것입니다. 대부분의 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 언어 수준에서 컴파일된다는 것을 알고 있습니다.
여러 개체를 쓰는 경우 배열이됩니다 –
전체 메시지를 읽어야한다는 것을 알고 계십니까? 이 코드에서는 메시지의 절반을 읽고 처리하려고 시도 할 것이므로 예외가 발생할 수 있습니다. 소켓에서 inputStream의 청크를 읽고 하프로드가 아닌 전체 청크 만 처리하는 프로토콜이 있어야합니다. –
Java 1.7을 사용하는 경우에는 finally 블록에서 생성기를 닫거나 "try-with-resources"에서 사용해야합니다. –