hadoop append - HDFS Java의 기존 파일에 데이터 추가




filewriter (4)

HDFS에서 기존 파일에 데이터를 추가하는 데 문제가 있습니다. 나는 그 파일이 존재한다면 줄을 추가하고 그렇지 않다면 주어진 이름으로 새로운 파일을 생성하기를 원한다.

HDFS에 기록하는 방법은 다음과 같습니다.

if (!file.exists(path)){
   file.createNewFile(path);
}

FSDataOutputStream fileOutputStream = file.append(path); 
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
br.append("Content: " + content + "\n");
br.close();

실제로이 방법은 HDFS에 쓴다.하지만 파일을 만들지 만 언급하지는 않는다.

이것이 내 방법을 테스트하는 방법입니다.

RunTimeCalculationHdfsWrite.hdfsWriteFile("RunTimeParserLoaderMapperTest2", "Error message test 2.2", context, null);

첫 번째 매개 변수는 파일의 이름이고 두 번째 매개 변수는 다른 매개 변수는 중요하지 않습니다.

누구나 제가 누락되거나 잘못하고있는 것에 대한 아이디어를 가지고 있습니까?


Answers

HDFS는 append 작업을 허용하지 않습니다. 추가 기능과 동일한 기능을 구현하는 한 가지 방법은 다음과 같습니다.

  • 파일이 있는지 확인하십시오.
  • 파일이 존재하지 않으면 새 파일을 만들고 새 파일에 쓰십시오
  • 파일이 있으면 임시 파일을 작성하십시오.
  • 원래 파일의 행을 읽고 같은 줄을 임시 파일에 씁니다 (줄 바꿈을 잊지 마십시오).
  • 임시 파일에 추가하려는 행을 작성하십시오.
  • 마지막으로 원본 파일을 삭제하고 임시 파일을 원래 파일로 이동 (이름 바꾸기)하십시오.

해결 .. .. !!

Append는 HDFS에서 지원됩니다.

다음과 같이 구성 및 간단한 코드를 수행하면됩니다.

1 단계 : hdfs-site.xml에서 dfs.support.append를 true로 설정하십시오.

<property>
   <name>dfs.support.append</name>
   <value>true</value>
</property>

stop-all.sh를 사용하여 모든 데몬 서비스를 중지하고 start-all.sh를 사용하여 다시 시작하십시오.

2 단계 (선택 사항) : 단 하나의 단일 클러스터가있는 경우 다음과 같이 복제 계수를 1로 설정해야합니다.

커맨드 라인을 통해 :

./hdfs dfs -setrep -R 1 filepath/directory

또는 자바 코드를 통해 런타임에 동일한 작업을 수행 할 수 있습니다.

fShell.setrepr((short) 1, filePath);  

3 단계 : 파일에 데이터 작성 / 추가 코드 :

public void createAppendHDFS() throws IOException {
    Configuration hadoopConfig = new Configuration();
    hadoopConfig.set("fs.defaultFS", hdfsuri);
    FileSystem fileSystem = FileSystem.get(hadoopConfig);
    String filePath = "/test/doc.txt";
    Path hdfsPath = new Path(filePath);
    fShell.setrepr((short) 1, filePath); 
    FSDataOutputStream fileOutputStream = null;
    try {
        if (fileSystem.exists(hdfsPath)) {
            fileOutputStream = fileSystem.append(hdfsPath);
            fileOutputStream.writeBytes("appending into file. \n");
        } else {
            fileOutputStream = fileSystem.create(hdfsPath);
            fileOutputStream.writeBytes("creating and writing into file\n");
        }
    } finally {
        if (fileSystem != null) {
            fileSystem.close();
        }
        if (fileOutputStream != null) {
            fileOutputStream.close();
        }
    }
}

친절하게 다른 도움을 위해 알려주세요.

건배.!!


실제로 HDFS 파일에 추가 할 수 있습니다.

Client의 관점에서, append 연산은 먼저 DistributedFileSystem의 append를 호출하고,이 연산은 stream 객체 FSDataOutputStream을 반환합니다. 클라이언트가이 파일에 데이터를 추가해야하는 경우 out.write를 작성하여 작성하고 out.close를 호출하여 닫을 수 있습니다.

HDFS 소스를 확인한 결과, DistributedFileSystem#append 메소드가 있습니다.

 FSDataOutputStream append(Path f, final int bufferSize, final Progressable progress) throws IOException

자세한 내용은 slideshare.net/dataera/inside-hdfs-append 참조하십시오.

또한 명령 줄을 통해 추가 할 수도 있습니다.

hdfs dfs -appendToFile <localsrc> ... <dst>

stdin에서 직접 행 추가 :

echo "Line-to-add" | hdfs dfs -appendToFile - <dst>

내가 아는 한, 자바는 가치에 의한 호출만을 알고있다. 즉, 원시 데이터 유형의 경우 사본으로 작업하고 객체에 대해서는 객체에 대한 참조 복사본으로 작업합니다. 그러나 나는 몇몇 함정이 있다고 생각한다; 예를 들어,이 작동하지 않습니다 :

public static void swap(StringBuffer s1, StringBuffer s2) {
    StringBuffer temp = s1;
    s1 = s2;
    s2 = temp;
}


public static void main(String[] args) {
    StringBuffer s1 = new StringBuffer("Hello");
    StringBuffer s2 = new StringBuffer("World");
    swap(s1, s2);
    System.out.println(s1);
    System.out.println(s2);
}

스왑 함수에서는 메인의 참조에 영향을주지 않는 copys를 사용하기 때문에 Hello World가 아닌 World Hello가 채워집니다. 그러나 객체가 변경되지 않는 경우 다음과 같이 변경할 수 있습니다.

public static void appendWorld(StringBuffer s1) {
    s1.append(" World");
}

public static void main(String[] args) {
    StringBuffer s = new StringBuffer("Hello");
    appendWorld(s);
    System.out.println(s);
}

그러면 Hello World가 명령 행에 채워집니다. StringBuffer를 String으로 변경하면 String이 변경되지 않으므로 Hello 만 생성됩니다. 예 :

public static void appendWorld(String s){
    s = s+" World";
}

public static void main(String[] args) {
    String s = new String("Hello");
    appendWorld(s);
    System.out.println(s);
}

그러나 String과 함께 사용할 수 있도록하는 String과 같은 래퍼를 만들 수 있습니다.

class StringWrapper {
    public String value;

    public StringWrapper(String value) {
        this.value = value;
    }
}

public static void appendWorld(StringWrapper s){
    s.value = s.value +" World";
}

public static void main(String[] args) {
    StringWrapper s = new StringWrapper("Hello");
    appendWorld(s);
    System.out.println(s.value);
}

편집 : 나는 이것이 문자열과 같은 불변의 객체로는 할 수없는 원래의 객체를 수정할 수 있기 때문에 두 개의 문자열을 "추가"할 때 이것이 StringBuffer를 사용하는 이유라고 생각한다.





java hadoop hdfs filewriter