읽기/쓰기를 바이트는 파일에서만 사용하 Java.IO

0

질문

우리는 어떻게 쓰는 바이트 배열 파일에(그리고 그것을 읽고 뒤에서는 파일)에서 Java?

예,우리는 모두 알고 있 이미 많은 질문들이 있지만,그들은 아주 지저분하고 주관적 사실에는 많은 방법이있다 이것을 달성하는 작업입니다.

그래서 그의 범위를 줄이는 질문:

도메인:

  • 안드로이드/자바

우리가 무엇을 원하는:

  • 빨리(가능)
  • 버그-무료(에서 엄격하게 세심한 방법)

우리가 무엇을 하지 않기:

  • 타사 라이브러리
  • 어떤 라이브러리를 필요로 하는 안드로이드 API 에 보다 나중 23 일(멜로)

(그래서,는 Apache Commons, 구글은 구아바, Java.nio,그리고 나뭇잎이 우리와 함께 좋은 ol'Java.io)

우리에게 무엇이 필요:

  • 바이트 배열은 항상 정확히 동일한(내용과 크기)를 통과 한 후 write--다음 읽기 프로세스
  • 쓰 방법만을 필요로는 두 개의 인수:파일의 파일 byte[]data
  • 읽는 방법을 반환 byte[]고 필요 인수는 파일을 파일

내 특정한 경우에,이 방법은 프라이빗(아 라이브러리)에 대해 책임지지 않습 다음,(하지만 당신이 원하는 경우를 만들기 더 보편적인 솔루션에 적용되는 넓은 관객이,그것을 위해 갈):

  • 스레드에 안전(파일에 접근할 수 없는 하나 이상의 과정에서 한 번)
  • 파일 null
  • 파일을 가리키는 존재하지 않 위치
  • 부족의 권한에서 파일 위치
  • 바이트 배열되고 너무 크
  • 바이트 배열되는 null
  • 을 다루는 모든"인덱스,""길"또는"append"인수/기능

그래서 우리의 종류에서의 검색 결정적인 방탄 코드는 사람들이 미래에 있다고 가정 사용하는 것이 안전하기 때문에 응답의 최대 투표 없는지 의견을 말하고,"는 충돌할 수 있습니다면..."

이것은 내가 지금까지:

쓰 바이트 파일:

private void writeBytesToFile(final File file, final byte[] data) {
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();
        } catch (Exception e) {
            Log.i("XXX", "BUG: " + e);
        }
    }

읽 바이트에서 파일

private byte[] readBytesFromFile(final File file) {
        RandomAccessFile raf;
        byte[] bytesToReturn = new byte[(int) file.length()];
        try {
            raf = new RandomAccessFile(file, "r");
            raf.readFully(bytesToReturn);
        } catch (Exception e) {
            Log.i("XXX", "BUG: " + e);
        }
        return bytesToReturn;
}

내가 읽고,예외가 있다:

FileNotFoundException:내가 올바른 이 발생하지 않아야 한 파일 경로 공급되고 있는 파생되었 안드로이드를 사용하여 자신의 내부 도구 및/또는 응용 프로그램을 테스트를 제대로?

IOException:지 않아요 정말 무엇이 원인일 수 있습니다...그러나 나는 가정하면 주위에 방법이 있다면 그것은 않습니다.

그래서 그 마음에 할 수 있습니다 이러한 방법을 개선되거나 대체,그렇다면,무엇을?

android arrays file java
2021-11-23 02:58:43
2

최고의 응답

6

그것은 다음과 같이 될 것 코어 유틸리티/라이브러리 방법에서 실행되어야 하는 안드로이드 API23 니다.

에 관한 라이브러리 방법,내가 그것을 찾을 수 있도록 최고 가정하지 않는 방법에 대한 응용 프로그램이 이러한 방법을 사용합니다. 경우에 따라서 응용 프로그램을 받고 싶은 체크 IOExceptions(기 때문에 파일에서 데이터가 존재해야 합 응용 프로그램을 위해 작업)를,다른 경우에는 응용 프로그램을 수 있습 걱정하지 않는 경우 데이터를 사용할 수 없기 때문에(파일에서 데이터만 캐쉬에 사용할 수도 있습니다 기본 소스).

올 때 I/O 작업을 없을 보장하는 작업이 성공할 것이다(예를 들어 사용자가 떨어지는 휴대 전화 화장실에서). 라이브러리를 반영해야 한 것을 응용 프로그램 선택을 처리하는 방법에 오류가 있습니다.

을 최적화하는 I/O 성능 항상 가"행복한 경로"오류를 잡는 그 밖으로 무엇을 잘못했습니다. 이것은 직 정상적인 프로그래밍하지만 필수적 처리에 저장 I/O. 예를 들어,다만인 경우는 파일이 존재하기 전에 파일을 읽는 응용 프로그램을 만들 수를 두 배로 느린 이러한 모든 종류의 I/O 작업을 빠르게 추가를 느리게 응용 프로그램니다. 가정은 파일이 존재하고 오류 메시지가 표시되는 경우,다음을 확인한 경우 파일이 존재합니다.

그래서 그 아이디어,주요 기능은 일반적인 형태는 다음과 같습니다.

public static void writeFile(File f, byte[] data) throws FileNotFoundException, IOException {
    try (FileOutputStream out = new FileOutputStream(f)) {
        out.write(data);
    }
}

public static int readFile(File f, byte[] data) throws FileNotFoundException, IOException {
    try (FileInputStream in = new FileInputStream(f)) {
        return in.read(data); 
    }
}

노트 구현에 대해:

  • 방법 또한 런타임 예외처 NullPointerExceptions 이 방법은 없을 것"버그".
  • 나는 생각하지 않는 버퍼링이 필요/에서 원하는 방법들을 통해 위기 때문에만 하나 기본화 수행 (또한 여기에서).
  • 이제 응용 프로그램 또한 옵션을 읽기의 시작에 불과합니다.

을 쉽게하기 위해 응용 프로그램 파일을 읽는 추가 방법 추가 할 수 있습니다. 하지만 그것은 라이브러리에 오류가 발견 및 보고하므로 응용 프로그램 응용 프로그램 자체할 수 있는 더 이상 감지하는 그 오류가 있습니다.

public static byte[] readFile(File f) throws FileNotFoundException, IOException {
    int fsize = verifyFileSize(f);
    byte[] data = new byte[fsize];
    int read = readFile(f, data);
    verifyAllDataRead(f, data, read);
    return data;
}

private static int verifyFileSize(File f) throws IOException {
    long fsize = f.length();
    if (fsize > Integer.MAX_VALUE) {
        throw new IOException("File size (" + fsize + " bytes) for " + f.getName() + " too large.");
    }
    return (int) fsize;
}

public static void verifyAllDataRead(File f, byte[] data, int read) throws IOException {
    if (read != data.length) {
        throw new IOException("Expected to read " + data.length 
                + " bytes from file " + f.getName() + " but got only " + read + " bytes from file.");
    }
}

이 구현에 다른 추가 숨겨진 지점의 실패:OutOfMemory 지점에서 새로운 데이터 배열이 만들어집니다.

맞게 응용 프로그램 추가,추가적인 방법이 도움을 추가할 수 있습으로 다른 시나리오니다. 예를 들어,말 응용 프로그램이 정말로 처리하지 않습으로 확인된 예외 사항:

public static void writeFileData(File f, byte[] data) {
    try {
        writeFile(f, data);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
}

public static byte[] readFileData(File f) {
    try {
        return readFile(f);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
    return null;
}

public static int readFileData(File f, byte[] data) {
    try {
        return readFile(f, data);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
    return -1;
}

private static void fileExceptionToRuntime(Exception e) {
    if (e instanceof RuntimeException) { // e.g. NullPointerException
        throw (RuntimeException)e;
    }
    RuntimeException re = new RuntimeException(e.toString());
    re.setStackTrace(e.getStackTrace());
    throw re;
}

방법 fileExceptionToRuntime 최소한의 구현,하지만 그것을 보여줍니다.

라이브러리 할 수 있도록 도와 줄 것 응용 프로그램를 해결하는 오류가 발생한 경우가 발생합니다. 예를 들어,방법 canReadFile(File f) 를 확인할 수 있는 경우는 파일이 존재하고 읽기 쉽고는 너무 큰되지 않습니다. 응용 프로그램을 수 있는 이러한 함수를 호출한 후 파일 읽기에 실패할 확인에 대한 일반적인 이유는 파일을 읽을 수 없습니다. 동일한 수행할 수 있습에 대한 파일에 쓰기.

2021-11-28 22:59:55

감사에 도움이 되는 유익한 대답합니다. 나는 그것을 함께 프로젝트에서 참조하는 경우 이해할 수 있습니다. 는 이유는 무엇인가에 대한 변경 readBytes 방법에 서명했던 것과는? (당신이 걸립 byte[]중 하나로서의 인수 및 반환 int). 또한이 당신의 최종 블록의 코드도의 일부가 될 수 있는 라이브러리 또는 응용 프로그램?
Nerdy Bunz

또한되지 않습니다 라인"return(int)f.length();"충돌기 때문 f.길이 보다 큰의 정수입니다.MAX_VALUE?
Nerdy Bunz

@NerdyBunz 에 대해 마지막 질문:아니다,"downcasting"을 제공하지 않습하는 오류를 이 경우에는 IOException 경우 발생 fsize 값은 너무 큽니다. 또한,내가 다시 사용 fsize 가 있기 때문에( f.length() 결과에서 I/O 작업).
vanOekel

에 대한 첫 번째 질문에:그것의 모든 것의 일부가 될 수 있습니다. 나 byte[] readFile(File f) 비슷한 byte[] readBytesFromFile(final File file). 나 byte[] readFileData(File f) 방법의 예는 어떻게 사용자 정의할 수 있는 이러한 기능이다. 하는 알아내는 방법을 노출시킬(public다)및 유지 숨겨진(private)그리고 나는 생각한 질문에 대답할 수 있는 방법 당신은 당신이 원하는 응용 프로그램을 사용하지 않고있는 제한적인 응용 프로그램?
vanOekel
3

할 수는 없지만 사용 하는 타사 라이브러리를 읽을 수 있습 그들의 코드와 그들의 경험에서 배울. 에서 구글은 구아바를 예를 들어,당신은 일반적으로 파일을 읽으로 바이트는 다음과 같다:

FileInputStream reader = new FileInputStream("test.txt");
byte[] result = ByteStreams.toByteArray(reader);

핵심 구현의 이 toByteArrayInternal. 를 호출하기 전에 이를 확인해야 합:

  • Not null 파일을 전달(nullpointerexception 이)
  • 파일이 있는(FileNotFoundException)

그 후,그것은 감소하는 취급하는 InputStream 이 IOExceptions 에서 왔습니다. 읽을 때 스트림의 많은 것을 제어 응용 프로그램의 잘못 갈 수 있습니다(나쁜 분야이고 다른 하드웨어 문제 mal 작동 드라이버 OS 액세스 권한)및 자신을 나타내는 IOException.

나는 복사기의 구현:

private static final int BUFFER_SIZE = 8192;

/** Max array length on JVM. */
private static final int MAX_ARRAY_LEN = Integer.MAX_VALUE - 8;

private static byte[] toByteArrayInternal(InputStream in, Queue<byte[]> bufs, int totalLen)
      throws IOException {
    // Starting with an 8k buffer, double the size of each successive buffer. Buffers are retained
    // in a deque so that there's no copying between buffers while reading and so all of the bytes
    // in each new allocated buffer are available for reading from the stream.
    for (int bufSize = BUFFER_SIZE;
        totalLen < MAX_ARRAY_LEN;
        bufSize = IntMath.saturatedMultiply(bufSize, 2)) {
      byte[] buf = new byte[Math.min(bufSize, MAX_ARRAY_LEN - totalLen)];
      bufs.add(buf);
      int off = 0;
      while (off < buf.length) {
        // always OK to fill buf; its size plus the rest of bufs is never more than MAX_ARRAY_LEN
        int r = in.read(buf, off, buf.length - off);
        if (r == -1) {
          return combineBuffers(bufs, totalLen);
        }
        off += r;
        totalLen += r;
      }
    }

    // read MAX_ARRAY_LEN bytes without seeing end of stream
    if (in.read() == -1) {
      // oh, there's the end of the stream
      return combineBuffers(bufs, MAX_ARRAY_LEN);
    } else {
      throw new OutOfMemoryError("input is too large to fit in a byte array");
    }
  }

당신이 볼 수있는 대부분의 논리 함께 할 수 있는 파일을 읽고 덩어리. 이것은 상황을 취급하기 위하여 당신이 알고하지 않는 크기의 InputStream,시작하기 전에 읽고 있습니다. 귀하의 경우에,당신은 필요한 파일을 읽기 당신은 알 수 있는 길이 미리 그렇게 이러한 복잡성을 피할 수 있습니다.

다른 체크인은 OutOfMemoryException. 표준 Java 제한은 너무 크고,그러나 안드로이드에서,그것은 훨씬 작은 값입니다. 확인해야 합니다 시도하기 전에 파일을 읽을 수 있는 충분한 사용할 수 있는 메모리.

2021-11-26 13:42:23

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................