Hadoopでのファイル読み書き(Java)
6298 ワード
前言
このドキュメントでは、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メソッドで呼び出すことはできません.
非Map Reduceプロセスでファイルを書く
このプロシージャはファイルの読み取りに対応しています.closeの前にBufferedWriterのflush()メソッドを呼び出すように注意してください.そうしないと、データが書かれません.
Mapまたはreduceメソッドでファイルを読み込む必要があるソリューション
大きなファイルの場合、現在のスキームは、このファイルを各クラスタノードに事前に配置することである可能性があります.ここでは2つの小さなファイルの処理方法について説明します.
方法1:実行中のjarパッケージにファイルをパッケージ化し(ルートディレクトリの下に置くことができます)、次の方法で読み込みます(file Nameはルートディレクトリの下で読み込むファイル名です).
メソッド2:MapまたはReduceクラスでpublic void configure(JobConf jobIn)メソッド(ベースクラスMapReduceBaseで定義)を複写する
このドキュメントでは、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 ***