OutputStream을 올바르게 닫는 방법은 무엇입니까?

justHelloWorld

아래에서 서버를 설정하기위한 생성자를 찾을 수 있습니다. 몇 즉, 그것이 읽기까지 있었던 마지막 시간에서 그 상태를 복원 List객체를 (라고 log)와 두 int(라고 currentTerm하고 votedFor). 나는이 필요하므로이 "휘발성"모든 필드가 업데이트됩니다 때마다, 상대 파일도 업데이트 (그래서 일관된 상태를 upadate하게)해야 할 것 ObjectOutPutStream이라고를 metadataWriter하고 logWriter. 서버가 언제든지 다운 될 수 있기 때문에 어떤 close()방법도 쓸 수 없습니다 . EOFException다음에 서버를 설정할 때 (읽기 작업 중) 를 피할 수있는 유일한 해결책은 flush()매번 출력 스트림 (코드의 마지막 줄에서 수행 한 것처럼 )하는 것이라고 생각하십니까?

   public ServerRMI(...)
    {
        ...
        log = new ArrayList<>();
        try {
            //if Log file exists then should exists Metadata too
            if(Files.exists(Paths.get("Server" + id + "Log"), LinkOption.NOFOLLOW_LINKS))
            {
                reader = new ObjectInputStream(new FileInputStream("Server"+id+"Log"));
                try
                {
                    while(true)
                        log.add((LogEntry) reader.readObject());
                }
                catch (EOFException e){}
                catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                reader = new ObjectInputStream(new FileInputStream("Server"+id+"Metadata"));
                currentTerm = reader.readInt();
                votedFor = reader.readInt();
            }
            else//if it is the first time that the server is set up initialize all persistent fields
            {
                currentTerm = 1;
                votedFor = -1;
                log = new ArrayList<LogEntry>();
            }
            logWriter = new ObjectOutputStream(new FileOutputStream("Server"+id+"Log"));
            metadataWriter = new ObjectOutputStream(new FileOutputStream("Server" + id + "Metadata"));
            //since creating a new ObjectOutputStream overwrite the old file with the an empty one, as first thing we rewrite the old content
            for(LogEntry entry : log)
                logWriter.writeObject(entry);
            metadataWriter.writeInt(currentTerm);
            metadataWriter.writeInt(votedFor);
            metadataWriter.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ...
    }

중요 사항:

누군가가 제안한 것처럼 리소스 를 사용하는 모든 방법 (및 서버의 상태를 업데이트하는 각 방법) 의 try-with-resources 가 실행 가능한 솔루션 이라고 생각하지 않습니다 . metadata파일에 대해 괜찮을 것이기 때문입니다 int. 파일을 업데이트 / 쓰기 할 때마다 항상 교체되지만, log파일의 경우 변경 될 때마다 전체 목록을 작성하는 것을 의미합니다 (작업이 추가 될뿐만 아니라 교체도 마찬가지입니다!). 성능에 좋지 않다는 것!

피터 로리

try-with-resource를 사용하고 한 번에 전체 컬렉션을 작성하는 것이 좋으며 예외가 발생할 때까지 읽을 필요가 없습니다. 처음에 메타 데이터를 쓸 수 있습니다.

List<LogEntry> entries = ..
try (ObjectOutputStream out = new ObjectOutputStream(....)) {
    out.writeObject(currentTerm);
    out.writeObject(votedeFor);
    out.writeObject(entries);
}

읽을 수 있습니다.

String currentTerm = "none";
String votedFor = "no-one";
List<LogEntry> entries = Collections.emptyList();
try (ObjectInputStream in = new ObjectInputStream(....)) {
    currentTerm = (String) in.readObject();
    votedFor = (String) in.readObject();
    entries = (List<LogEntry>) in.readObject();
}

참고 : Java 7이 필요하지만 곧 EOL이 될 예정이므로 가능하면 Java 8로 업그레이드하는 것이 좋습니다.

성능에 좋지 않다고 생각합니다!

이것은 매우 다른 질문이지만 여전히 try-with-resource를 사용합니다. 해결책은 새 항목 만 추가하는 것입니다. 이렇게하려면 다음이 필요합니다.

  • 파일에 추가를 지원하는 ObjectOutputStream 상단의 프로토콜. ObjectOutputStream은이 작업을 수행하지 않습니다. 대신 데이터 블록을 작성해야하며이를 함께 붙일 수단이 필요합니다.
  • 디스크에 마지막으로 쓴 이후 변경 / 추가 된 사항을 확인하고 변경 사항 만 디스크에 기록하는 방법.

성능이 나쁘다고 가정하기 전에 몇 밀리 초를 절약하기 위해 추가 된 복잡성이 가치가 없다는 것을 알 수 있으므로 테스트해야합니다.

BTW 당신이 정말로 성능에 관심이 있다면 ObjectOutputStream을 사용하지 마십시오. 일반적이고 유연하지만 매우 느립니다.

따라서 OutpuStreamObject (생성자 지역 변수가 아닌 클래스 필드)가 올바르게 닫히지 않습니다.

이 경우 파일이 손상됩니다. 파일의 유효성을 검사하고 유효하지 않은 데이터를 자르는 방법이 필요합니다.


내가 쓴 도서관을보세요. Chronicle Queue 지원하므로 많은 문제를 해결할 수 있습니다.

  • 여러 스레드, 프로세스 또는 기계에서 연속 쓰기.
  • 프로세스 나 스레드가 쓰는 동안 죽으면 손상된 항목이 잘 리거나 무시됩니다.
  • 쓰기 사이에 프로세스가 종료되면 데이터 손실이 없습니다.
  • 보다 효율적인 직렬화 수단을 지원합니다.
  • 마이크로 초 지연 시간으로 작성되는 동안 여러 스레드 / 프로세스에서 읽을 수 있습니다.
  • 배포를 위해 여러 시스템에 복제 할 수 있습니다.
  • 항목은 인덱스 또는 이진 검색을 통해 무작위로 액세스 할 수 있습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

소켓을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

Firefox OS 앱을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

QFile / FILE * : 핸들을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

양식을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

try-with-resources 내에서 OutputStream을 올바르게 사용하는 방법은 무엇입니까?

분류에서Dev

PDFTron에서 사용하는 파일을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

콘솔을 닫을 때 SIGBREAK를 올바르게 처리하는 방법은 무엇입니까?

분류에서Dev

콘솔을 닫을 때 SIGBREAK를 올바르게 처리하는 방법은 무엇입니까?

분류에서Dev

현재 양식을 닫고 새 양식을 올바르게 여는 방법은 무엇입니까?

분류에서Dev

이 방법을 올바르게 UnitTest하는 방법은 무엇입니까?

분류에서Dev

C ++에서 프로그램을 올바르게 닫는 방법은 무엇입니까?

분류에서Dev

폴더 이름을 올바르게 바꾸는 방법은 무엇입니까?

분류에서Dev

ValidateAntiForgeryToken을 올바르게 사용하는 방법은 무엇입니까?

분류에서Dev

babel 7 polyfill을 올바르게 연결하는 방법은 무엇입니까?

분류에서Dev

출력을 올바르게 교체하는 방법은 무엇입니까?

분류에서Dev

GPU 전력을 올바르게 활용하는 방법은 무엇입니까?

분류에서Dev

numpy 배열을 올바르게 스택하는 방법은 무엇입니까?

분류에서Dev

확인란을 올바르게 정렬하는 방법은 무엇입니까?

분류에서Dev

GetModuleFileName을 올바르게 사용하는 방법은 무엇입니까?

분류에서Dev

파티션을 올바르게 정렬하는 방법은 무엇입니까?

분류에서Dev

std :: string을 ""와 올바르게 비교하는 방법은 무엇입니까?

분류에서Dev

NSURLConnection 호출을 올바르게 수행하는 방법은 무엇입니까?

분류에서Dev

srcML을 올바르게 설치하는 방법은 무엇입니까?

분류에서Dev

자산을 올바르게 생성하는 방법은 무엇입니까?

분류에서Dev

GraphQLList 및 GraphQLInterfaceType을 올바르게 사용하는 방법은 무엇입니까?

분류에서Dev

LLVMModule 및 LLVMExecutionEngine을 올바르게 제거하는 방법은 무엇입니까?

분류에서Dev

List <string>을 올바르게 나누는 방법은 무엇입니까?

분류에서Dev

PHP 확장을 올바르게 설치하는 방법은 무엇입니까?

분류에서Dev

비동기 작업을 올바르게 잡는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    소켓을 올바르게 닫는 방법은 무엇입니까?

  2. 2

    Firefox OS 앱을 올바르게 닫는 방법은 무엇입니까?

  3. 3

    QFile / FILE * : 핸들을 올바르게 닫는 방법은 무엇입니까?

  4. 4

    양식을 올바르게 닫는 방법은 무엇입니까?

  5. 5

    try-with-resources 내에서 OutputStream을 올바르게 사용하는 방법은 무엇입니까?

  6. 6

    PDFTron에서 사용하는 파일을 올바르게 닫는 방법은 무엇입니까?

  7. 7

    콘솔을 닫을 때 SIGBREAK를 올바르게 처리하는 방법은 무엇입니까?

  8. 8

    콘솔을 닫을 때 SIGBREAK를 올바르게 처리하는 방법은 무엇입니까?

  9. 9

    현재 양식을 닫고 새 양식을 올바르게 여는 방법은 무엇입니까?

  10. 10

    이 방법을 올바르게 UnitTest하는 방법은 무엇입니까?

  11. 11

    C ++에서 프로그램을 올바르게 닫는 방법은 무엇입니까?

  12. 12

    폴더 이름을 올바르게 바꾸는 방법은 무엇입니까?

  13. 13

    ValidateAntiForgeryToken을 올바르게 사용하는 방법은 무엇입니까?

  14. 14

    babel 7 polyfill을 올바르게 연결하는 방법은 무엇입니까?

  15. 15

    출력을 올바르게 교체하는 방법은 무엇입니까?

  16. 16

    GPU 전력을 올바르게 활용하는 방법은 무엇입니까?

  17. 17

    numpy 배열을 올바르게 스택하는 방법은 무엇입니까?

  18. 18

    확인란을 올바르게 정렬하는 방법은 무엇입니까?

  19. 19

    GetModuleFileName을 올바르게 사용하는 방법은 무엇입니까?

  20. 20

    파티션을 올바르게 정렬하는 방법은 무엇입니까?

  21. 21

    std :: string을 ""와 올바르게 비교하는 방법은 무엇입니까?

  22. 22

    NSURLConnection 호출을 올바르게 수행하는 방법은 무엇입니까?

  23. 23

    srcML을 올바르게 설치하는 방법은 무엇입니까?

  24. 24

    자산을 올바르게 생성하는 방법은 무엇입니까?

  25. 25

    GraphQLList 및 GraphQLInterfaceType을 올바르게 사용하는 방법은 무엇입니까?

  26. 26

    LLVMModule 및 LLVMExecutionEngine을 올바르게 제거하는 방법은 무엇입니까?

  27. 27

    List <string>을 올바르게 나누는 방법은 무엇입니까?

  28. 28

    PHP 확장을 올바르게 설치하는 방법은 무엇입니까?

  29. 29

    비동기 작업을 올바르게 잡는 방법은 무엇입니까?

뜨겁다태그

보관