json傳二進制文件(轉)
前幾天,項目中需要在socket中傳輸二進制文件.
這本來是很簡單的事,因為我們知道socket傳輸的就是字節流.所以非常簡單.
java的實現:
Java代碼
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileReceive {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8800);
System.out.println("server started!");
while (true) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
int i;
while ((i = inputStream.read()) != -1) {
fileOutputStream.write(i);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
serverSocket.close();
break;
}
}
}
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class FileSend {
public static void main(String[] args) throws Exception {
// 打開文件流
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
Socket socket = new Socket("127.0.0.1", 8800);
OutputStream outputStream = socket.getOutputStream();
int i;
// 讀取並寫入socket
while ((i = fileInputStream.read()) != -1) {
outputStream.write(i);
}
// 結束
outputStream.flush();
socket.close();
}
}
測試的時候先運行FileReceive,再運行FileSend
這樣你就能看到在D:/下有一個文件是"b.png".跟原來的一模一樣.代表傳輸成功!
不過我們的項目有個要求,需要用json的協議來傳輸.
我們都知道json是文本格式.所以我馬上想到的是把文件編碼成文本,再進行傳輸.
所以關鍵就是要把一個二進制文件翻譯成文本,再翻譯回去.如果可以,也就代表這個方案是可行的.
馬上我就寫出了第一個版本:
Java代碼
// 讀取文件
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
while ((i = fileInputStream.read()) != -1) {
byteArrayOutputStream.write(i);
}
fileInputStream.close();
// 把文件存在一個字節數組中
byte[] filea = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
String fileaString = new String(filea);
System.out.println(fileaString);
// 寫入文件
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
fileOutputStream.write(fileaString.getBytes());
fileOutputStream.flush();
fileOutputStream.close();
發現b.png根本無法打開,很是奇怪?而且大小也不一樣了.
檢查代碼后發現把數組轉化成string的時候后面還可以加個參數charset[編碼名稱].
於是馬上改了一下:
.......
String fileaString = new String(filea,"uft-8");
.......
fileOutputStream.write(fileaString.getBytes("utf-8"));
結果還是不行,又改了一下:
.......
String fileaString = new String(filea,"ISO-8859-1");
.......
fileOutputStream.write(fileaString.getBytes("ISO-8859-1"));
結果成功了.
結合以前的編碼知識,總算是想明白了.
把字節數組轉換成字符串時,如果charset為空,那就表示用你的默認編碼進行轉換.
而不管gb2312和utf8都不是用單字節表示一個字符的.只要他不認識的,他就會默認轉換成一個特定字符,所以這樣的轉換是不可逆的.
只有像ascii這樣的單字節編碼的轉換才是可逆的.
明白了這個道理.我們就可以用json協議來傳任何的數據了.^_^,大功告成!
有關編碼的問題我推薦阮一峰的一篇博文,對字符編碼有很好的解釋.
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
這本來是很簡單的事,因為我們知道socket傳輸的就是字節流.所以非常簡單.
java的實現:
Java代碼
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileReceive {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8800);
System.out.println("server started!");
while (true) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
int i;
while ((i = inputStream.read()) != -1) {
fileOutputStream.write(i);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
serverSocket.close();
break;
}
}
}
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class FileSend {
public static void main(String[] args) throws Exception {
// 打開文件流
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
Socket socket = new Socket("127.0.0.1", 8800);
OutputStream outputStream = socket.getOutputStream();
int i;
// 讀取並寫入socket
while ((i = fileInputStream.read()) != -1) {
outputStream.write(i);
}
// 結束
outputStream.flush();
socket.close();
}
}
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileReceive {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8800);
System.out.println("server started!");
while (true) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
int i;
while ((i = inputStream.read()) != -1) {
fileOutputStream.write(i);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
serverSocket.close();
break;
}
}
}
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class FileSend {
public static void main(String[] args) throws Exception {
// 打開文件流
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
Socket socket = new Socket("127.0.0.1", 8800);
OutputStream outputStream = socket.getOutputStream();
int i;
// 讀取並寫入socket
while ((i = fileInputStream.read()) != -1) {
outputStream.write(i);
}
// 結束
outputStream.flush();
socket.close();
}
}
測試的時候先運行FileReceive,再運行FileSend
這樣你就能看到在D:/下有一個文件是"b.png".跟原來的一模一樣.代表傳輸成功!
不過我們的項目有個要求,需要用json的協議來傳輸.
我們都知道json是文本格式.所以我馬上想到的是把文件編碼成文本,再進行傳輸.
所以關鍵就是要把一個二進制文件翻譯成文本,再翻譯回去.如果可以,也就代表這個方案是可行的.
馬上我就寫出了第一個版本:
Java代碼
// 讀取文件
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
while ((i = fileInputStream.read()) != -1) {
byteArrayOutputStream.write(i);
}
fileInputStream.close();
// 把文件存在一個字節數組中
byte[] filea = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
String fileaString = new String(filea);
System.out.println(fileaString);
// 寫入文件
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
fileOutputStream.write(fileaString.getBytes());
fileOutputStream.flush();
fileOutputStream.close();
// 讀取文件
FileInputStream fileInputStream = new FileInputStream("d:/a.png");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
while ((i = fileInputStream.read()) != -1) {
byteArrayOutputStream.write(i);
}
fileInputStream.close();
// 把文件存在一個字節數組中
byte[] filea = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
String fileaString = new String(filea);
System.out.println(fileaString);
// 寫入文件
FileOutputStream fileOutputStream = new FileOutputStream("d:/b.png");
fileOutputStream.write(fileaString.getBytes());
fileOutputStream.flush();
fileOutputStream.close();
發現b.png根本無法打開,很是奇怪?而且大小也不一樣了.
檢查代碼后發現把數組轉化成string的時候后面還可以加個參數charset[編碼名稱].
於是馬上改了一下:
.......
String fileaString = new String(filea,"uft-8");
.......
fileOutputStream.write(fileaString.getBytes("utf-8"));
結果還是不行,又改了一下:
.......
String fileaString = new String(filea,"ISO-8859-1");
.......
fileOutputStream.write(fileaString.getBytes("ISO-8859-1"));
結果成功了.
結合以前的編碼知識,總算是想明白了.
把字節數組轉換成字符串時,如果charset為空,那就表示用你的默認編碼進行轉換.
而不管gb2312和utf8都不是用單字節表示一個字符的.只要他不認識的,他就會默認轉換成一個特定字符,所以這樣的轉換是不可逆的.
只有像ascii這樣的單字節編碼的轉換才是可逆的.
明白了這個道理.我們就可以用json協議來傳任何的數據了.^_^,大功告成!
有關編碼的問題我推薦阮一峰的一篇博文,對字符編碼有很好的解釋.
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
