用JAVA访问文件共享系统[转]

用JAVA 访问共享文件系统

功能:用JAVA实现访问局域网上某台机器上的共享文件或者文件夹,可以对其进行操作。

一、首先介绍下SMBCIFS

SMB(Server Message Block 服务器消息块)协议Microsoft网络系统中用来实现共享局域网内文件和打印机的协议。用于在计算机间共享文件,打印机甚至是串口,SMB 协议可以用在因特网的TCP/IP协议上。也可以用在其它的网络协议上。

SMB 一种客户机/服务器、请求/响应协议。通过 SMB 协议,客户端应用程序可以在各种网络环境下读、写服务器上的文件,以及对服务器程序提出服务请求。在TCP/IP环境下,客户机通过NetBIOS over TCP/IP(或 SPX/IPX)连接服务器。一旦连接成功,客户机可发送 SMB 命令到服务器上,从而客户机能够访问共享目录、打开文件、读写文件,以及一切在文件系统上能做的所有事情。

CIFS(Common Internet File System 通用网际文件系统)是微软服务器消息块协议(SMB)的增强版本,是计算机用户在企业内部网和因特网上共享文件的标准方法。CIFS 通过定义一种与应用程序在本地磁盘和网络文件服务器上共享数据的方式相兼容的远程文件访问协议使之能够在因特网上进行协作。

CIFS 提供如下关键特点:

1、文件访问的完整性:CIFS 支持一套通用的文件操作:打开、关闭、读,写以及搜索。CIFS 也支持文件和记录的锁定和解锁。CIFS 允许多个客户端访问和更新同一个文件,它通过提供文件共享和文件锁定功能来避免发生冲突。

2、为慢速链接优化:CIFS 已被优化过,使之能在慢速拨号线路上良好运行,结果就是为使用调制解调器访问因特网的用户提供了改善的性能。

3、安全性:CIFS 服务器既支持匿名传输,也支持对于指定文件的安全的、需要验证的访问。同时,也易于管理文件和目录的安全策略。

4、高性能和可扩展性:CIFS 服务器和操作系统高度集成,为最大化系统性能而优化。CIFS 支持 Windows 95 之后的所有微软平台。它也支持其它流行的操作系统,如 UNIX、VMS、Macintosh 、IBM LAN server等。

5、使用统一码(Unicode)文件名:文件名可以使用任何字符集,而不局限于为英语或西欧语言设计的字符集。

6、全局文件名:用户不必挂载远程文件系统也能直接查阅到全局有效名称,而不是只有本地意义的那些名称。

二、JAVACIFS 实现

Jcifs是CIFS在JAVA中的一个实现,是samba组织本着linux的精神,负责维护开发的一个开源项目。这个项目专注于使用java语言对 cifs协议的设计和实现。他们将jcifs设计成为一个完整的,丰富的,具有可扩展能力且线程安全的客户端库。这一库可以应用于各种java虚拟机访问 遵循CIFS/SMB网络传输协议的网络资源。类似于java.io.File的接口形式,在多线程的工作方式下被证明是有效而容易使用的。

我们可以通过http://jcifs.samba.org/src/docs/api/来了解他的功能以及主要用法。我也是初步了解这方面的内容,就简单介绍下它里面我们常用并且简单的部分。

Jcifs通过类似如下的资源url定位一个资源:

smb://guest:[email protected]/share/a.txt

url开始的部分smb://表示这是一个smb类型的url,下面的guest和q123ew分别是访问共享资源的用户名和密码,@后面的192.168.3.56是要访问资源所在的主机名或IP地址,share//a.txt是共享资源的目录和文件名。

在JAVA 程序中,使用如下方式获得一个远程共享文件的句柄:

SmbFile? file? =? new SmbFile(smb://guest:[email protected]/share/a.txt);

通过SmbFile? file? =? new SmbFile(smb://guest:[email protected]/)可以得到该机器上的所有共享文件的一个句柄。注意:后面的“/”是不可少的。

这里的句柄不仅限于远程的共享文件,还可能是共享文件夹。isFile()方法和isDirectory()用来判断这个句柄对应的资源的真实属性。如果 是共享文件夹,通过调用它的list()、listFiles()方法将获得其中资源的列表。List方法支持过滤器机制,有两种过滤器可供使用,一种是 SmbFileFilter,另一种是SmbFilenameFilter,这两个在jcifs中作为接口出现,你可以根据自己的需要派生出个性化的过滤 器,实现接口中的accept方法,以满足不同业务的需求.

当然也提供对文件的读写方法,基本上和JAVA里面的java.io.File一样。

二、举例

下面的这个例子是实现获取局域网某机器上的所用贡献目录及目录下的文件。

package com.test.file;

import java.util.LinkedHashSet;

import java.util.Stack;

import jcifs.smb.SmbFile;

import jcifs.smb.SmbFileFilter;

?

public class SmbTest {

??? ??? public static void main(String args[]) {

?????? ??? System.out.println("测试用CIFS访问文件共享系统");

?????? ??? ?String url = "smb://guest:@192.168.1.128/";

?????? ??? try {

?????????? ??? SmbFile file = new SmbFile(url);

?????????? ??? SmbFile[] list = findSharefiles(file);

?????????? ??? for (int j = 0; j < list.length; j++) {

????????????? ??? if(list[j].isDirectory()) {

????????????????? ??? System.out.println(list[j].getCanonicalPath());

????????????? ??? }

????????????? ??? if (list[j].isFile()) {

????????????????? ??? System.out.println("??? " + list[j].getName());

????????????? ??? }

?????????? ??? }

?????? ??? } catch (Exception e) {

?????????? ??? e.printStackTrace();

?????? }

??? }

?

??? public static SmbFile[] findSharefiles(SmbFile dir) {

?????? Stack curPath = new Stack();

?????? curPath.push(dir);

?????? return findFiles(curPath);

??? }

?

??? public static final int FIND_SUB = 0; // 找子节点

??? public static final int FIND_SIB = 1; // 找同级节点

??? public static final int FIND_END = 2; // 结束

?

??? public static SmbFile[] findFiles(Stack curPath) {

??????

?????? class MyDirFilter implements SmbFileFilter {

?????????? public boolean accept(SmbFile pathname) {

????????????? try {

????????????????? return (pathname != null) && pathname.isDirectory();

????????????? } catch (Exception e) {

????????????????? return false;

????????????? }

?????????? }

?????? }

??????

?????? class MyFileFilter implements SmbFileFilter {

?????????? public boolean accept(SmbFile pathname) {

????????????? try {

????????????????? return (pathname != null) && pathname.isFile();

????????????? } catch (Exception e) {

????????????????? return false;

????????????? }

?????????? }

?????? }

?

?????? MyDirFilter dirFilter = new MyDirFilter();

?????? MyFileFilter fileFilter = new MyFileFilter();

?????? int state = FIND_SUB; // 开始

?????? LinkedHashSet found = new LinkedHashSet();

?????? while (state != FIND_END) {

?????????? SmbFile dir = (SmbFile) curPath.pop(); // 当前目录

?????????? if (state == FIND_SUB) { // 查找子节点

????????????? SmbFile[] subDirs = null;

????????????? try {

????????????????? subDirs = dir.listFiles(dirFilter);

????????????? } catch (Exception e) {

????????????? }

????????????? if (subDirs == null || subDirs.length == 0) { // 没有子点

????????????????? curPath.push(dir);

????????????????? state = FIND_SIB; // 下一次需要找同级节点

????????????? } else {

????????????????? curPath.push(dir);

????????????????? curPath.push(subDirs[0]);

????????????????? state = FIND_SUB;

????????????? }

?????????? } else if (state == FIND_SIB) { // 查找同级节点

????????????? SmbFile[] files = null;

????????????? try {

????????????????? files = dir.listFiles(fileFilter);

????????????? } catch (Exception e) {

????????????? }

????????????? if (files != null) {

????????????????? for (int i = 0; i < files.length; i++) {

???????????????????? found.add(files[i]);

????????????????? }

????????????? }

????????????? if (curPath.isEmpty()) {

????????????????? state = FIND_END; // 已经没有可以找的了,需要退出查找过程

????????????? } else {

????????????????? SmbFile parentDir = (SmbFile) curPath.peek();

????????????????? SmbFile[] sibDirs = null;

????????????????? try {

???????????????????? sibDirs = parentDir.listFiles(dirFilter);

????????????????? } catch (Exception e) {

????????????????? }

????????????????? for (int i = 0; i < sibDirs.length; i++) {

?

???????????????????? if (dir.equals(sibDirs[i])) { // 找到了当前的位置

???????????????????????? found.add(sibDirs[i]);

???????????????????????? if (i + 1 < sibDirs.length) { // 存在下一个同级节点

??????????????????????????? curPath.push(sibDirs[i + 1]);

??????????????????????????? state = FIND_SUB; // 需要查找子节点

???????????????????????? } else { // 这就是最后一个同级节点

??????????????????????????? state = FIND_SIB;

???????????????????????? }

???????????????????????? break;

???????????????????? }

????????????????? }

????????????? }

?????????? }

?????? }

?????? return (SmbFile[]) found.toArray(new SmbFile[found.size()]);

??? }

}

这个代码还不严谨,我测试的时候当存在有共享打印机大目录时就会抛异常,我就在listFiles(dirFilter)方法上加了捕捉异常但没有处理,这样如果抛了异常,还能运行,只是共享打印机这个目录就找不到了.

Api:http://jcifs.samba.org/src/docs/api/

jar包:http://jcifs.samba.org/src/

引用:http://blog.sina.com.cn/s/blog_4e8549e701000cyp.html

你可能感兴趣的:(用JAVA访问文件共享系统[转])