【问题标题】:How to specify path of a file in java/terminal on Hadoop?如何在 Hadoop 上的 java/terminal 中指定文件的路径?
【发布时间】:2017-03-24 18:21:36
【问题描述】:

我在 Hadoop2 上运行一个任务:

$hadoop jar hipi.jar "/5" "/processWOH" 1

hipi.jar:jar文件名

“/5”:输入文件夹名称

"/processWOH": 输出文件夹名称

我收到关于路径 /localhost:9000/5/LC814000.tif: 的异常:

Error: java.io.FileNotFoundException: /localhost:9000/5/LC814000.tif (No such file or directory)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at ProcessWithoutHIPI.ProcessRecordReaderWOH.getCurrentKey(ProcessRecordReaderWOH.java:81)
        at ProcessWithoutHIPI.ProcessRecordReaderWOH.getCurrentKey(ProcessRecordReaderWOH.java:1)
        at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.getCurrentKey(MapTask.java:507)
        at org.apache.hadoop.mapreduce.task.MapContextImpl.getCurrentKey(MapContextImpl.java:70)
        at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.getCurrentKey(WrappedMapper.java:81)
        at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:145)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:764)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:340)
        at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:167)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1548)
        at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:162)

我认为(我不确定)添加到路径中的额外“/localhost:9000”的问题,但我不知道它是如何添加的(通过 hadoop,java 代码,...)。

注意:这个 jar 文件在 hadoop 之外运行良好,但在 hadoop (hdfs) 中却不是

感谢任何帮助

更新: 正如我后来发现的那样,“/5”文件夹是在本地系统中搜索的,而不是在 hdfs 中,如果我在本地文件系统中创建一个名为“localhost:9000”的文件夹,在根目录下,即 /localhost:9000 并放入“/5”代码将运行,但在这种情况下,数据是从 hadoop 外部获取的,就像我根本不使用 hadoop 一样。 那么这是编程中的一个错误,即我应该使用hadoop io包而不是java io包来处理hdfs而不是本地文件系统,还是另一个问题。?

【问题讨论】:

  • 前缀/localhost:9000是关于hdfs的路径;请执行以下命令并传递结果:$hadoop fs -ls /localhost:9000/
  • @Imi.Cino 谢谢。我现在明天早上不在办公室,我会运行它并提交结果。
  • /localhost:9000 不是floder; 9000是你的hdfs的端口!您可以在 core-site.xml 中看到它。请出示你的 core-site.xml 和你的 mapreduce 程序
  • @Imi.Cino 对于正确的情况确实如此,但在我的情况下,它从本地系统而不是 hdfs 获取所有路径,我不知道为什么。正因为如此,我在本地系统中创建了一个文件夹 /localhost:9000/ 并且它工作但现在所有数据都在 Hadoop 之外获取和写入!!
  • @Imi.Cino fs.default.namehdfs://localhost:9000配置>

标签: java hadoop jar terminal path


【解决方案1】:

你的hdfs的默认目录是/localhost:9000/,hadoop在那里找不到你的输入文件;刚刚过去 /localhost:9000/:

$hadoop fs -put $LOCAL_PATH_OF_INPUT_FILE:/5 /localhost:9000/
$hadoop jar hipi.jar "/5" "/processWOH" 1

祝你好运!

【讨论】:

  • 谢谢。好吧,谢谢没有用。你能看到我帖子的更新吗?
  • 请看下面我的回答。
【解决方案2】:

正如我之前所说,问题是 Java IO(即文件类、路径类……)将路径视为本地文件系统中的路径,而 Hadoop Io(文件系统类、路径类……)将路径视为在 HDFS 中。

请看这里: read/write from/in HDFS

使用 FileSystem API 向 HDFS 读写数据

可以通过多种方式从 Hadoop 分布式文件系统 (HDFS) 读取数据和向其中写入数据。现在让我们首先使用 FileSystem API 在 HDFS 中创建和写入文件,然后应用程序从 HDFS 读取文件并将其写回本地文件系统。

第 1 步:下载测试数据集后,我们可以编写应用程序从本地文件系统读取文件并将内容写入 Hadoop 分布式文件系统。

package com.hadoop.hdfs.writer;

import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Tool;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.ToolRunner;

public class HdfsWriter extends Configured implements Tool {

    public static final String FS_PARAM_NAME = "fs.defaultFS";

    public int run(String[] args) throws Exception {

        if (args.length < 2) {
            System.err.println("HdfsWriter [local input path] [hdfs output path]");
            return 1;
        }

        String localInputPath = args[0];
        Path outputPath = new Path(args[1]);

        Configuration conf = getConf();
        System.out.println("configured filesystem = " + conf.get(FS_PARAM_NAME));
        FileSystem fs = FileSystem.get(conf);
        if (fs.exists(outputPath)) {
            System.err.println("output path exists");
            return 1;
        }
        OutputStream os = fs.create(outputPath);
        InputStream is = new BufferedInputStream(new FileInputStream(localInputPath));
        IOUtils.copyBytes(is, os, conf);
        return 0;
    }

    public static void main( String[] args ) throws Exception {
        int returnCode = ToolRunner.run(new HdfsWriter(), args);
        System.exit(returnCode);
    }
}

第 2 步: 导出 Jar 文件并从终端运行代码以将示例文件写入 HDFS:

[training@localhost ~]$ hadoop jar HdfsWriter.jar com.hadoop.hdfs.writer.HdfsWriter sample.txt /user/training/HdfsWriter_sample.txt

第三步:验证文件是否写入HDFS并查看文件内容:

[training@localhost ~]$ hadoop fs -cat /user/training/HdfsWriter_sample.txt

第 4 步:接下来,我们编写一个应用程序来读取我们刚刚在 Hadoop 分布式文件系统中创建的文件,并将其内容写回本地文件系统:

package com.hadoop.hdfs.reader;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class HdfsReader extends Configured implements Tool {

    public static final String FS_PARAM_NAME = "fs.defaultFS";

    public int run(String[] args) throws Exception {

        if (args.length < 2) {
            System.err.println("HdfsReader [hdfs input path] [local output path]");
            return 1;
        }

        Path inputPath = new Path(args[0]);
        String localOutputPath = args[1];
        Configuration conf = getConf();
        System.out.println("configured filesystem = " + conf.get(FS_PARAM_NAME));
        FileSystem fs = FileSystem.get(conf);
        InputStream is = fs.open(inputPath);
        OutputStream os = new BufferedOutputStream(new FileOutputStream(localOutputPath));
        IOUtils.copyBytes(is, os, conf);
        return 0;
    }

    public static void main( String[] args ) throws Exception {
        int returnCode = ToolRunner.run(new HdfsReader(), args);
        System.exit(returnCode);
    }
}

第 5 步: 导出 Jar 文件并从终端运行代码以将示例文件写入 HDFS:

[training@localhost ~]$ hadoop jar HdfsReader.jar com.hadoop.hdfs.reader.HdfsReader /user/training/HdfsWriter_sample.txt /home/training/HdfsReader_sample.txt

第6步:验证文件是否写回本地文件系统:

[training@localhost ~]$ hadoop fs -cat /user/training/HdfsWriter_sample.txt

FileSystem 是一个代表通用文件系统的抽象类。大多数 Hadoop 文件系统实现都可以通过 FileSystem 对象进行访问和更新。要创建 HDFS 的实例,请调用方法 FileSystem.get()。 FileSystem.get() 方法将查看分配给类路径上 Hadoop 配置文件的 fs.defaultFS 参数的 URI,并选择要实例化的 FileSystem 类的正确实现。 HDFS 的 fs.defaultFS 参数的值为 hdfs://。

一旦创建了 FileSystem 类的实例,HdfsWriter 类就会调用 create() 方法在 HDFS 中创建文件。 create() 方法返回一个 OutputStream 对象,可以使用普通的 Java I/O 方法对其进行操作。同样HdfsReader调用open()方法在HDFS中打开一个文件,返回一个InputStream对象,可以用来读取文件的内容。

文件系统 API 非常广泛。为了演示 API 中可用的其他一些方法,我们可以向我们创建的 HdfsWriter 和 HdfsReader 类添加一些错误检查。

要在调用 create() 之前检查文件是否存在,请使用:

boolean exists = fs.exists(inputPath);

要检查路径是否为文件,请使用:

boolean isFile = fs.isFile(inputPath);

要重命名已存在的文件,请使用:

boolean renamed = fs.rename(inputPath, new Path("old_file.txt"));

【讨论】:

  • 导出jar文件之前是怎么编译的?
  • @Imi.Cino 使用 Eclipse。我包含了所有必需的 Hadoop 包。然后项目将其导出为可运行的 jar。
  • 我不确定,但我建议您使用以下命令编译它:javac -classpath ${HADOOP_HOME}/lib/hadoop-core-1.2.1.jar /path_calasses.java跨度>
  • @Imi.Cino 大多数时候,您需要大量其他库,以便更好地使用 IDE 进行开发。祝你好运!
猜你喜欢
  • 1970-01-01
  • 2020-12-12
  • 2015-06-04
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
相关资源
最近更新 更多