我在将二进制文件(在Hadoop中存储为序列文件)复制到本地机器时遇到问题。问题是,我从hdfs下载的二进制文件不是我在运行map-还原任务时生成的原始二进制文件。我搜索了类似的问题,我想问题是,当我将序列文件复制到我的本地机器时,我得到了序列文件的头加上原始文件。
我的问题是:是否有任何方法可以避免下载标题,但仍然保留我的原始二进制文件?
有两种方法我可以考虑:
我不知道哪一个可行。有人能给我一个解决办法吗?你还能给我一些你给出的解决方案的示例代码吗?
我非常感谢你的帮助。
发布于 2015-11-07 08:16:57
我找到了解决这个问题的办法。由于下载序列文件将为您提供二进制文件中的标题和其他神奇单词,因此我避免此问题的方法是将原始二进制文件转换为Base64字符串,并将其作为文本存储在HDFS中,当下载编码的二进制文件时,我将其解码回原始二进制文件。
我知道这将需要额外的时间,但目前我没有找到任何其他解决这个问题的办法。直接删除序列文件中的头和其他神奇单词的困难部分是Hadoop可能在我的二进制文件之间插入一些单词"Sync“。
如果有人对这个问题有更好的解决办法,我会很高兴听到的。:)
发布于 2017-09-20 10:48:48
使用MapReduce代码读取SequenceFile,并使用SequenceFileInputFormat作为InputFileFormat读取HDFS中的序列文件。这将将文件拆分为键值对,并且该值将只包含二进制文件内容,您可以使用这些内容来创建二进制文件。
下面是一个代码片段,用于拆分由多个图像组成的序列文件,并将其拆分为单独的二进制文件,并将其写入本地文件系统。
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class CreateOrgFilesFromSeqFile {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
if (args.length !=2){
System.out.println("Incorrect No of args (" + args.length + "). Expected 2 args: <seqFileInputPath> <outputPath>");
System.exit(-1);
}
Path seqFileInputPath = new Path(args[0]);
Path outputPath = new Path(args[1]);
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "CreateSequenceFile");
job.setJarByClass(M4A6C_CreateOrgFilesFromSeqFile.class);
job.setMapperClass(CreateOrgFileFromSeqFileMapper.class);
job.setInputFormatClass(SequenceFileInputFormat.class);
job.setOutputKeyClass(NullWritable.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, seqFileInputPath);
FileOutputFormat.setOutputPath(job, outputPath);
//Delete the existing output File
outputPath.getFileSystem(conf).delete(outputPath, true);
System.exit(job.waitForCompletion(true)? 0 : -1);
}
}
class CreateOrgFileFromSeqFileMapper extends Mapper<Text, BytesWritable, NullWritable, Text>{
@Override
public void map(Text key, BytesWritable value, Context context) throws IOException, InterruptedException{
Path outputPath = FileOutputFormat.getOutputPath(context);
FileSystem fs = outputPath.getFileSystem(context.getConfiguration());
String[] filePathWords = key.toString().split("/");
String fileName = filePathWords[filePathWords.length-1];
System.out.println("outputPath.toString()+ key: " + outputPath.toString() + "/" + fileName + "value length : " + value.getLength());
try(FSDataOutputStream fdos = fs.create(new Path(outputPath.toString() + "/" + fileName)); ){
fdos.write(value.getBytes(),0,value.getLength());
fdos.flush();
}
//System.out.println("value: " + value + ";\t baos.toByteArray().length: " + baos.toByteArray().length);
context.write(NullWritable.get(), new Text(outputPath.toString() + "/" + fileName));
}
}
https://stackoverflow.com/questions/33548652
复制相似问题