用Java Serialization实现任意文件网络传输
来源:互联网 发布:农村人口老龄化数据 编辑:程序博客网 时间:2024/06/03 16:10
摘要:
本文通过Java中提供的Serialization机制,通过网络(Socket)实现任意文件在不同机器之间的传输。本文将包含两个实验的代码:
1. 将文件从一个电脑(客户端),传送到另外一个电脑(服务端);
2. 将文件从一个Android 2.1手机(客户端),通过WiFi传送到电脑(服务端)。
很多朋友发现在两台机器之间,通过TCP socket传送文件的时候,所得到的文件要么比源文件大,要么比源文件小。尤其是在传递多媒体文件的时候,由于文件大小的变化,最终导致多媒体文件无法正常播放。造成这种情况的原因有很多,但100%是程序自身的问题。同样,解决的办法也有很多,本文所介绍的两个小实验,就是试图采用Java中提供的Serialization机制,来解决这样的问题。
实验一:
1. 先创建一个Java项目,项目名为ObjectClient,作为客户端应用。在这个项目中创建一个实现了Serializable接口的类FilePojo,代码如下:
package com.pnf.transfer;
import java.io.Serializable;
// 必须实现Serializable接口。否则无法调用ObjectOutputStream的
// writeObject方法,或者ObjectInputStream中的readObject方法
public class FilePojo implements Serializable
{
private static final long serialVersionUID = 1L;
private String fileName; // 文件名称
private long fileLength; // 文件长度
private byte[] fileContent; // 文件内容
public String getFileName()
{
return fileName;
}
public void setFileName(String fileName)
{
this.fileName = fileName;
}
public long getFileLength()
{
return fileLength;
}
public void setFileLength(long fileLength)
{
this.fileLength = fileLength;
}
public byte[] getFileContent()
{
return fileContent;
}
public void setFileContent(byte[] fileContent)
{
this.fileContent = fileContent;
}
}
这个类将在服务器端也会被用到。
2. 编写客户端代码如下
package com.pnf.transfer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ObjectClient
{
public static void main(String[] args)
{
String serverName = "192.168.0.10"; // 服务器IP
int port = 6666; // 服务器端口
String filePath = "E:\\"; // 要传递文件的路径
String fileName = "full.jpg"; // 要传递文件的名称
try
{
// 连接服务器
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
// 创建FilePojo对象
FilePojo fpo = new FilePojo();
// 设定文件名
fpo.setFileName(fileName);
// 设定文件大小
File f = new File(filePath + fileName);
long fileLength = f.length();
fpo.setFileLength(fileLength);
// 读取文件内容,并将其转换为byte[]
FileInputStream fis = new FileInputStream(filePath + fileName);
byte[] fileContent = new byte[(int) fileLength];
fis.read(fileContent, 0, (int) fileLength);
fpo.setFileContent(fileContent);
// 将FilePojo对象fpo写到Socket client指定的输出流
long start = System.currentTimeMillis();
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeObject(fpo);
long end = System.currentTimeMillis();
System.out.println("It takes " + (end - start) + "ms");
oos.flush();
oos.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
3. 创建另外一个Java项目,项目名为ObjectServer,作为服务端应用。把第1步中的FilePojo.java拷贝到这个项目中来。
4. 编写服务端代码如下:
package com.pnf.transfer;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ObjectServer
{
public static void main(String[] args) throws ClassNotFoundException
{
ServerSocket serverSocket;
FileOutputStream fos;
try
{
serverSocket = new ServerSocket(6666);
while(true)
{
Socket clientSocket = serverSocket.accept();
// 从clientSocket获取ObjectInputStream对象
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
// 读取从客户端传递过来的FilePojo对象
FilePojo fpo = (FilePojo) ois.readObject();
System.out.println(fpo.getFileName());
System.out.println(fpo.getFileLength());
// 初始化FileOutputStream对象fos
fos = new FileOutputStream("D:\\" + fpo.getFileName());
// 将fpo中的内容写入fpo
fos.write(fpo.getFileContent(), 0, (int)fpo.getFileLength());
fos.close();
ois.close();
}
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}
5. 测试。
先运行服务端,在运行客户端。
在局域网上,传输的速度大致为:传输162149bytes需要20ms,即8KB/ms或8MB/s
实验二:
服务端的代码和实验一中的一样。
1. 创建一个Android项目,项目名为AndroidObjectClient作为客户端。并将实验一中的FilePojo.java拷贝到该项目中。
2. 修改main.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:id="@+id/btn_send"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send a picture to PC!"
>
</Button>
</LinearLayout>
3. 编写Activity的代码如下:
package com.pnf.transfer;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class AndroidObjectClientActivity extends Activity
implements
OnClickListener
{
private Button btn_send;
private String filePath = "/sdcard/image/";
private String fileName = "bln.jpg";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn_send = (Button)this.findViewById(R.id.btn_send);
btn_send.setOnClickListener(this);
}
public void onClick(View v)
{
try
{
// 建立和服务器的连接
Socket socket = new Socket("192.168.0.10", 6666);
// 创建FilePojo对象
FilePojo fpo = new FilePojo();
// 设定文件名
fpo.setFileName(fileName);
// 设定文件大小
File f = new File(filePath + fileName);
long fileLength = f.length();
fpo.setFileLength(fileLength);
// 读取文件内容,并将其转换为byte[]
FileInputStream fis = new FileInputStream(filePath + fileName);
byte[] fileContent = new byte[(int) fileLength];
fis.read(fileContent, 0, (int) fileLength);
fpo.setFileContent(fileContent);
// 将FilePojo对象fpo写到Socket client指定的输出流
long start = System.currentTimeMillis();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(fpo);
long end = System.currentTimeMillis();
Toast.makeText(this.getApplicationContext(), "It takes " + (end - start) + "ms", Toast.LENGTH_LONG).show();
oos.flush();
oos.close();
}
catch(Exception ioe)
{
ioe.printStackTrace();
}
}
}
4. 在AndroidManifest.xml中增加permission如下(粗体字部分):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pnf.transfer"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidObjectClientActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
第一个permission,表示该程序可以读取sd卡上的内容,第二个permission,表示该程序可以联网(因为我们用到了TCP/IP)。
5. 在手机上安装编译好的AndroidObjectClient.apk。
6. 运行。
先运行服务端,再在手机上运行客户端。
在WLAN(802.11g)网上,传输的速度大致为:传输218089bytes需要200ms,即1.1KB/ms或1.1MB/s。如果是802.11n的话,传输速度应该会快很多。
当然,也可以将一个文件,通过DDMS放到模拟器中模拟的SD卡里面,然后在模拟器中运行客户端,这点在实验中也经过验证了的。
- 用Java Serialization实现任意文件网络传输
- 用Java Serialization实现任意文件网络传输
- 用Java Serialization实现任意文件网络传输
- Java 网络编程 之 传输对象 Serialization 序列化
- 网络间通信socket传输任意格式任意大小的文件
- 网络间通信socket传输任意格式任意大小的文件
- 【无浪】用Socket类实现网络传输文件软件
- java多线程网络传输文件(非同步)
- java-网络编程-大文件极限传输
- java tcp网络通信 传输文件
- Java Nio 实现文件的传输
- java实现SFTP传输文件例子
- linux网络传输文件
- C++ Builder文件任意分割传输技术
- python 实现网络传输
- linux网络编程-UDP实现文件的传输
- java 网络传输
- java socket多线程网络传输多个文件
- Microsoft Interview: In binary tree, find two nodes' nearest common father
- 最小堆实现
- 2.3-删除链表中间节点
- 山东省2013高职分数线
- 进程与线程的一个简单解释
- 用Java Serialization实现任意文件网络传输
- 判断对象在堆上的代码例子
- Java实现线性表
- UVA10650 - Determinate Prime - 数论
- 九:基于xmpp的聊天
- 中断上下文和进程上下文
- Java8学习笔记(1) -- 从函数式接口说起
- JavaFX文档(5)开始JavaFX之旅——3 使用CSS
- java 入门