Hadoopでのファイル読み書き(Java)


前言
このドキュメントでは、JavaインタフェースでHadoop分散システムのファイルを読み書きする方法や、符号化の変換などの問題について説明します.中には細部がありますが、あなたが知らないときは、非常に間違いやすいです.こちらの読み書きファイルは以下の3つの状況に分けられます.
    1. 非Map Reduceプロセスでの分散ファイルシステム内のファイルの読み書き
例えば、あなたは自分で1つのファイルを遍歴したいと思って、1つのファイルを遮断したいと思って、すべてこのような方法に属します.一般にこのプロセスはrun関数で発生し,プログラマはMap Reduceによって生成された中間ファイルを処理する.
    2. map(またはreduce)関数でレコードを読み書きします.
TextInputFormatの場合、レコードは1行です.行としてTextオブジェクトを取得します.読み込んだファイルがUTF-8形式でない場合(例えばGBK、TextInputFormatはUTF-8ファイルしか復号できないため、直接読むと文字化けしてしまう)、Unicodeに正しく変換する方法に注意してください.
    3. map(またはreduce)関数で、ファイルを読み書きします.
たとえばmap関数では、読み込みファイルでHashMapを初期化したいとします.
非Map Reduceプロセスでファイルを読み込む
主にFileSystemクラスを使い、ファイルを開いてFSDataInputStreamを手に入れます.このFSDataInputStreamはデータをキャッシュすると言われているので、BufferedReaderにパッケージする必要はありませんが、readLine()メソッドはdeprecatedなので、一行の読みを考えて、BufferedReaderに変えましょう.変換の過程で、入力ファイルの符号化を指定することもできます.例えば、こちらは「UTF-8」です.このファイルの読み取り方法は、staticクラスにあり、JobConfを作成できないため、mapまたはreduceメソッドで呼び出すことはできません.
JobConf confQ = new JobConf(getConf(), XXXX.class);
FileSystem fs= FileSystem.get(confQ);
FSDataInputStream fin = fs.open(new Path("filePathXX"));
BufferedReader in = null;
String line;
try {
	in = new BufferedReader(new InputStreamReader(fin, "UTF-8"));
	while ((line = in.readLine()) != null) {
		//...
	}

} finally {
	if (in != null) {
		in.close();
	}
}

非Map Reduceプロセスでファイルを書く
このプロシージャはファイルの読み取りに対応しています.closeの前にBufferedWriterのflush()メソッドを呼び出すように注意してください.そうしないと、データが書かれません.
JobConf confQ = new JobConf(getConf(), XXXX.class);
FileSystem fs= FileSystem.get(confQ);
FSDataOutputStream fout = fs.create(new Path("         "));
BufferedWriter out = null;
try {
	out = new BufferedWriter(new OutputStreamWriter(fout, "UTF-8"));
	out.write("XXXXXX");
	out.newLine();
	}
	out.flush();
} finally {
	if (out != null) {
		out.close();
	}
}

Mapまたはreduceメソッドでファイルを読み込む必要があるソリューション
大きなファイルの場合、現在のスキームは、このファイルを各クラスタノードに事前に配置することである可能性があります.ここでは2つの小さなファイルの処理方法について説明します.
方法1:実行中のjarパッケージにファイルをパッケージ化し(ルートディレクトリの下に置くことができます)、次の方法で読み込みます(file Nameはルートディレクトリの下で読み込むファイル名です).
BufferedReader in = null;
try {
	InputStream fstream = Thread.currentThread()
			.getContextClassLoader().getResourceAsStream("fileName");
	in = new BufferedReader(new InputStreamReader(new DataInputStream(
			fstream), "UTF-8"));
	String line;
	while ((line = in.readLine()) != null) {
		//...
	}
} finally {
	in.close();
}

メソッド2:MapまたはReduceクラスでpublic void configure(JobConf jobIn)メソッド(ベースクラスMapReduceBaseで定義)を複写する
public void configure(JobConf jobIn) {
    super.configure(jobIn);
    try{
		FileSystem fs = null;
		fs = FileSystem.get(jobIn);
		FSDataInputStream in;
		BufferedReader bufread;
		String strLine;
		String[] strList;
		IpField ipField;
		Path IpCityPath = new Path("/user/hadoop/dw/dim/ip_cityid.txt");
        if (!fs.exists(IpCityPath))
            throw new IOException("Input file not found");
        if (!fs.isFile(IpCityPath))
            throw new IOException("Input should be a file");
        in = fs.open(IpCityPath);
        bufread = new BufferedReader(new InputStreamReader(in));
        while ((strLine = bufread.readLine()) != null) {
            strList =strLine.split("\"");
            if(strList.length  
  

CityIpLocal ArrayList

map GBK

    , 。 GBK ,map , Text.toString Unicode, Java Unicode , , :

Text value;//map     
String line = new String(value.getBytes(), 0, value.getLength(),"GBK");

こちらで したGBKは み みファイルの を し、lineはUnicodeに した を します. に するのは、こちらがvalueを する があることです.getBytes()で られたbyte の と さ、(0,value.getLength()).String line=new String(value.getBytes()、「GBK」);このようにして られる 、 に な がある があります. では、Textオブジェクトが され、byte (char かもしれない)を して を し、 はこの を から きするだけで、 で かなければ の はまだあります.
のことばを する
TextInputFormatでファイルを として する 、mapの valueはTextタイプであり、text で にメンテナンスされているのはbyte であり、 ファイルから byte で み まれ、byteには されません. ファイルのバイトストリームはtextのbyte に ります.
Textは をutf 8とする、Textを び す.toString,Textは byteをutf 8として い, み んだファイルの の がgbkであれば
けしが しますこのときnew String(Text.getBytes(),0,Text.getLength()、「 ファイルの の 」)は、 しいエスケープを します.
TextOutputFormatを とすると、reduceプロセスはutf 8 を します.しかし、このステップには さなtrikyがあり、Textの はTextを び します.getBytesメソッドは,Text にbytte として されているため, には のコンテンツを くことができる.
:
    1. HadoopのTextInput/TextOutputはシステムコードに く なく、コードによってUTF 8にハードライトされています.
    2. TextとStringではデータの が います.
Map Reduce はGBKファイル
これは がくれた の の です. にはTextOutputFormatが コードをUTF-8と いてしまったので、 でこれを えてGBKを することができます.
Excelで できるエンコーディング(Unicode)として
に じて、 に されたファイルをExcelで く があります. の では、タブでフィールドを することで、Excelで なるバーとして できます. なのは された である. してみると、ローカルのExcelファイルはUnicodeで されていることがわかり、JavaプログラムにUnicode、またはUTF-16と されていたが、 だめだった.もう ると、もともと なのは のUnicodeで、デフォルトのUTF-16は のものを していたので、UTF-16 LEに して、 のものに しました. し、 で しく くことはできたが、Excelで くことはできなかった. で した 、バイト を する があった(BOM,Byte Order Mark). に のようなコードを きました(この でUTF-8のファイルをUnicodeに しました):
private void convertToUnicode(FSDataInputStream convert_in,
			FSDataOutputStream convert_out,String head) throws IOException {
	BufferedReader in = null;
	BufferedWriter out = null;
	try {
		in = new BufferedReader(new InputStreamReader(convert_in, "UTF-8"));
		out = new BufferedWriter(new OutputStreamWriter(convert_out,
				"UTF-16LE"));
		out.write("\uFEFF");
		out.write(head+"
"); String line; while ((line = in.readLine()) != null) { out.write(line); out.newLine(); } out.flush(); } finally { if(in!=null) in.close(); if(out!=null) out.close(); } }

ここにはもう つ すべき がありますwrite("\uFEFF");Unicode のBOMはFFFEのはずなのに、こちらはなぜ なのか べることができます. はJavaのバイトコード が で、uFEFFはメモリでFFが ( アドレス)、FEが 、 き し がFFFE(UltraEditor 16 で ると、 かにそうです).こちらの はマシンのサイズ とは ないはずです.
:http://www.cnblogs.com/noures/archive/2012/08/17/2643841.html
:java apiを してHadoopファイルを する
*** walker ***