HDFS API文件上传,fs.default.name配置的关键性 – CodeWeblog.com

综上所述:
无论我们是在代码中对”fs.default.name”进行配置,还是直接拷贝core-site.xml和hdfs-site.xml到当前工程下,最终我们的目的都是要实现对fs.default.name的配置。
只有对fs.default.name成功配置后,我们才能成功上传文件到远程客户端。
java中可以这样设置
conf.set(“fs.default.name”, “hdfs://master:9000”);
conf.set(“mapred.job.tracker”, “master:9001”);
或者拷贝core-site.xml和hdfs-site.xml到当前工程下。

<span class="hljs-tag">Exception</span> <span class="hljs-tag">in</span> <span class="hljs-tag">thread</span> "<span class="hljs-tag">main</span>" <span class="hljs-rule"><span class="hljs-attribute">java.lang.IllegalArgumentException</span>:<span class="hljs-value"> Wrong FS: hdfs://master:<span class="hljs-number">9000</span>/index.html, expected:</span></span>

file:///

at org.apache.hadoop.fs.FileSystem.checkPath(FileSystem.java:390)

at org.apache.hadoop.fs.RawLocalFileSystem.pathToFile(RawLocalFileSystem.java:55)

at org.apache.hadoop.fs.LocalFileSystem.pathToFile(LocalFileSystem.java:61)

at org.apache.hadoop.fs.LocalFileSystem.exists(LocalFileSystem.java:51)

at org.apache.hadoop.fs.FileUtil.checkDest(FileUtil.java:355)

at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:211)

at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:163)

at org.apache.hadoop.fs.LocalFileSystem.copyFromLocalFile(LocalFileSystem.java:67)

at org.apache.hadoop.fs.FileSystem.copyFromLocalFile(FileSystem.java:1178)

at com.lango.mapreduce.example.chainmapper.Test.fsCopy(Test.java:32)

at com.lango.mapreduce.example.chainmapper.Test.main(Test.java:25)

 

 

1、Wrong FS: hdfs://master:9000/index.html, expected: file:///

 

 

a、解决方案:复制core-site.xml和hdfs-site.xml到当前工程下

 

因为是访问远程的HDFS, 需要通过URI来获得FileSystem:

hadoop需要把集群上的core-site.xml和hdfs-site.xml放到当前工程下(eclipse工作目录的bin文件夹下面)

注意:

在我的Eclipse工作目录中没有找到bin文件夹。

HDFS API文件上传,fs.default.name配置的关键性

网上资料说“生成的class文件在项目目录中的bin目录下”,具体说法见下段参考资料:

生成的class文件在你的项目目录中的bin目录下,进入你的项目目录,可以看到一个.classpath文件,其中源文件地址,class文件存放地址,以及环境变量都是在这里面配置的,当然你可以通过myeclipse的界面配置,不过配置完成后都是修改的这个文件,<classpathentry kind=”src” path=”src”/>这个就是配置源文件存放地址,<classpathentry kind=”lib” path=”lib/activemq-console-4.1.1.jar”/>这些是将哪个目录的那个jar包导入到path中<classpathentry kind=”output” path=”classes”/>这个是生成的class文件存放到哪,其中目录可以为绝对目录,相对目录是相对当前目录来说的,也就是项目目录本身

所以,我觉得bin目录就是我目录结构中的build/classes文件。因此,拷贝core-site.xml和hdfs-site.xml到build/classes目录中。

再次运行之前的代码:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

public class FsTest {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

FileSystem fs = FileSystem.get(conf);

Path src = new Path(“C:/Users/lango/Desktop/core-site.xml”);

Path dst = new Path(“hdfs://master:9000/qj”);

fs.copyFromLocalFile(src, dst);

}

}

 

运行通过。文件成功上传,问题解决。

 

2、问题引申:通过几种对文件操作方式的比较,来总结对于把文件上传到远程客户端什么是最关键的因素。

 

b、拷贝core-site.xml和hdfs-site.xml到当前工程下,修改目标路径形式为如下形式:

<span class="hljs-regexp">//</span>注意和“Path dst = <span class="hljs-keyword">new</span> Path(<span class="hljs-string">"hdfs://master:9000/qj"</span>);”形式区分

Path dst = new Path(“/qj”);

 

整体代码如下:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

public class CopyToHDFS {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

FileSystem fs = FileSystem.get(conf);

fs.copyFromLocalFile(new Path(“/home/wqj/opt/140702152709log.txt”), new Path(“/qj”));

}

}

 

程序运行正常,文件上传成功。

c、不拷贝core-site.xml和hdfs-site.xml到当前工程下。配置

conf.<span class="hljs-built_in">set</span>(<span class="hljs-string">"fs.default.name"</span>, <span class="hljs-string">"hdfs://master:9000"</span>);

 

直接使用FileSystem类实现上传,代码如下:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

public class CopyToHDFS {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

conf.set(“fs.default.name”, “hdfs://master:9000”);

FileSystem fs = FileSystem.get(conf);

fs.copyFromLocalFile(new Path(“/home/wqj/opt/140702152709log.txt”), new Path(“/qj”));

}

}

 

运行通过,文件上传到远程HDFS上成功。

d、拷贝core-site.xml和hdfs-site.xml到当前工程下。直接使用FileSystem类实现上传,代码如下:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.hdfs.DistributedFileSystem;

public class FsTest {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

FileSystem fs = FileSystem.get(conf);

fs.copyFromLocalFile(new Path(“C:/Users/lango/Desktop/core-site.xml”), new Path(“/qj-dfs”));

}

}

 

运行通过,文件成功上传。

e、不拷贝core-site.xml和hdfs-site.xml到当前工程下。直接使用FileSystem类实现上传,代码和b完全相同。

和b做对比,有一个奇妙的现象。

HDFS API文件上传,fs.default.name配置的关键性

我们上传的文件它并没有被上传到远程HDFS中,而是跑到本地Eclipse工作目录所在根目录E盘下了。并且可看见文件的存放形式:.qj.crc和qj。

Eclipse控制台输出日志信息如下:

八月 <span class="hljs-number">12</span>, <span class="hljs-number">2014</span> <span class="hljs-number">2</span>:<span class="hljs-number">47</span>:<span class="hljs-number">41</span> 下午 org.apache.hadoop.util.NativeCodeLoader &lt;clinit&gt;

WARNING: Unable to load native-hadoop library for your platform… using builtin-java classes where applicable

 

运行通过,文件未成功上传到远程HDFS中,而是被上传到Eclipse工作目录所在根目录下了。

f、不拷贝core-site.xml和hdfs-site.xml到当前工程下。直接使用DistributedFileSystem类实现上传,代码如下:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.hdfs.DistributedFileSystem;

public class FsTest {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

conf.set(“fs.default.name”, “hdfs://master:9000”);

DistributedFileSystem fs = (DistributedFileSystem) FileSystem.get(conf);

Path src = new Path(“C:/Users/lango/Desktop/core-site.xml”);

Path dst = new Path(“/qj-dfs”);

fs.copyFromLocalFile(src, dst);

}

}

 

运行通过,文件成功上传。

注意:在d中,若省略“

conf.<span class="hljs-built_in">set</span>(<span class="hljs-string">"fs.default.name"</span>, <span class="hljs-string">"hdfs://master:9000"</span>);

 

”则程序报错。报错信息

Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"main"</span> java.lang.ClassCastException: org.apache.hadoop.fs.LocalFileSystem cannot be cast to org.apache.hadoop.hdfs.DistributedFileSystem

at com.lango.mapreduce.example.chainmapper.FsTest.main(FsTest.java:16)

 

解决方案:拷贝core-site.xml和hdfs-site.xml到当前工程下。整体代码不改变,代码如下:

<span class="hljs-keyword">package</span> com.lango.mapreduce.example.chainmapper;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.hdfs.DistributedFileSystem;

public class FsTest {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

// 省略fs.default.name配置

// conf.set(“fs.default.name”, “hdfs://master:9000”);

DistributedFileSystem fs = (DistributedFileSystem) FileSystem.get(conf);

Path src = new Path(“C:/Users/lango/Desktop/core-site.xml”);

Path dst = new Path(“/qj-dfs”);

fs.copyFromLocalFile(src, dst);

}

}

 

运行通过,文件上传成功。

通过上面一系列自己都觉得很晕的比较之后,感觉,无论怎么变,它们之间的最大区别就在于

fs.<span class="hljs-reserved">default</span>.name属性的配置

 

conf.<span class="hljs-built_in">set</span>(<span class="hljs-string">"fs.default.name"</span>, <span class="hljs-string">"hdfs://master:9000"</span>);

 

综上所述:

无论我们是在代码中对”fs.default.name”进行配置,还是直接拷贝core-site.xml和hdfs-site.xml到当前工程下,最终我们的目的都是要实现对fs.default.name的配置。

只有对fs.default.name成功配置后,我们才能成功上传文件到远程客户端。

来源URL:http://www.codeweblog.com/hdfs-api%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0-fs-default-name%E9%85%8D%E7%BD%AE%E7%9A%84%E5%85%B3%E9%94%AE%E6%80%A7/