文件传输

 

package com.kum.im.file;

import java.nio.channels.SocketChannel;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.ByteBuffer;

import java.io.RandomAccessFile;

import java.io.FileOutputStream;

import java.io.File;

import java.io.IOException;

import java.nio.channels.ClosedChannelException;

/**

* <p>Title: Socekt编程学习</p>

*

* <p>Description: 文件传输接收端</p>

*

* <p>Copyright: Copyright (c) 2009</p>

*

* <p>Company: <a href="www.kum.net.cn">酷猫科技</a></p>

*

* @author 贺翔<380595305@qq.com>

* @version 1.0

*/

public class ReveiceThread extends Thread {

private FileUtil util = new FileUtil();

private SocketChannel r_channel = null;

private ByteBuffer buf = ByteBuffer.allocate(util.getBlockSize() + 9);

public ReveiceThread(SocketChannel channel) throws Exception {

this.r_channel = channel;

this.r_channel.configureBlocking(false);

}

public void run() {

try {

Selector selector = Selector.open();

SelectionKey key = r_channel.register(selector, SelectionKey.OP_READ);

buf.clear();

File file = null;

FileOutputStream fout = null;//文件输出流对象

RandomAccessFile raf = null;//创建临时文件对象

int FileSize = 0; //文件大小

String FileName = ""; //文件名称

int BlockIndex = 0; //文件块索引号

int BlockSize = 0; //文件块大小

int readlen = 0; //读到的数据长度

int buflen = 0; //buf的长度

byte cmd = 0x0; //命令码

int BlockNum = 0; // 文件块数据计数器

int CompSize = 0; //已经完成数

while (key.selector().isOpen()) {

int selkey = selector.select();

if (selkey == 0) {

readlen = this.r_channel.read(buf); //开始读数据

buflen += readlen; //记录缓冲区buf的长度

if (readlen >= 1) { //读到了数据

buf.rewind(); ///数据指针指到0

cmd = buf.get(); //读取一个字节,获得文件头信息,判断发送信息类型(head or body)

switch (cmd) {

case 0x1: { ///文件信息

if (buflen >= 260) {

FileSize = buf.getInt(); //获取文件大小

byte[] filename = new byte[255];

buf.get(filename); //从缓冲区中读取255个字节,获取文件名

FileName = (new String(filename)).trim();

buf.compact(); //删除读取过的数据

buflen -= 260; //缓冲区大小减去已读的260个字节大小

buf.position(buflen); //数据指针指向buf的最后位置

System.out.println("文件名-->:" + FileName + ",文件大小-->:" +

FileSize);

fout = new FileOutputStream(FileName);

file = new File("~" + FileName + ".tmp"); //创建临时文件

raf = new RandomAccessFile(file, "rw"); //向临时文件中写入数据

System.out.println("文件创建成功,开始写入数据...");

}

else {

buf.position(buflen); ///数据指针指向buf的最后位置

}

}

break;

case 0x2: { //文件主体数据(body)

if (buflen >= 9) {

BlockIndex = buf.getInt(); //获得文件块索引号

BlockSize = buf.getInt(); //获得文件块大小

if (buflen >= (9 + BlockSize)) { //缓冲区大小减去已读数据

byte[] blockdb = new byte[BlockSize];

buf.get(blockdb); //读取文件块数据

buf.compact(); //删除已读数据

buflen -= (9 + BlockSize);

buf.position(buflen); //数据指针指向buf缓冲区最后位置

if (BlockSize < util.getBlockSize()) {

//如果收到的数据块大小小于定义的最大文件块大小

byte[] tmpdb = new byte[util.getBlockSize()]; ///定义临时最大数据块

System.arraycopy(blockdb, 0, tmpdb, 0, BlockSize);//

raf.seek( (util.getBlockSize() + 4) * BlockIndex); //(+4)是用于存放文件大小信息的

//文件块写入临时文件中将相应数据块放到相应的位置中去

raf.writeInt(BlockSize); //向临时数据块中写入文件大小信息

raf.write(tmpdb); //向临时数据块中写入文件块信息

BlockNum++; //文件块计数器累加

}

else {

//收到的数据等于文件块定义的最大值

raf.seek( (util.getBlockSize() + 4) * BlockIndex);

//文件块写入临时文件中将相应数据块放到相应的位置中去

raf.writeInt(BlockSize);

raf.write(blockdb);

BlockNum++;//文件块计数器累加

}

System.out.println("写入临时文件完成: ---->" +

(CompSize += BlockSize) + "****");

FileSize -= BlockSize; ///每收到一块,就从总文件大小里减去

if (FileSize == 0) { ///如果减到0了,说明文件块已经收全了,可以关闭文件了。

for (int i = 0; i < BlockNum; i++) {

//根据文件块个数循环将临时文件写入正式文件

raf.seek( (util.getBlockSize() + 4) * i);

BlockSize = raf.readInt();//从临时文件中读取文件块大小

byte[] tmpdb = new byte[BlockSize];

raf.read(tmpdb);//从临时文件中读取文件块数据

fout.write(tmpdb);//向正式文件中写入文件块

}

raf.close();//释放资源

file.delete(); ///删除临时文件

fout.close();

System.out.println("*******文件已经接收完成了!*******");

}

}

else {

buf.position(buflen); ///数据指针指向buf的最后位置

}

}

else {

buf.position(buflen); ///数据指针指向buf的最后位置

}

}

break;

}

}

}

}

}

catch (ClosedChannelException ex) {

System.out.println("发生ClosedChannelException异常,原因 ----> :" + ex.getMessage());

}

catch (IOException ex) {

System.out.println("打开选择器时异常,原因 ----> :" + ex.getMessage());

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值