写入文字
我们可以首先看我们编码器的编码格式
可以看到文件是UTF-8的编码格式。
UTF-8对于中文的编码是用三个字节进行存储,对于英文字符是利用一个字节进行存储的。我们进行代码验证可得知,但是这次我们采用二者相互转化却不利用这种方式。
方法一
public static void main(String[] args) {
String s = "我";
byte[] b = s.getBytes();
System.out.println("b.length = "+b.length);
String es = "a";
byte[] eb = es.getBytes();
System.out.println("eb.length = "+eb.length);
}
我们进行字符串和字节数组的转换,再把得到的字节数组转为字符串一网打尽。
客户端:进行字符串的发送
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",9090);
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
String s = "吃hhhh";
out.write(s.getBytes().length);
for (int i = 0; i < s.length(); i++) {
byte[] bytes = char2byte(s.charAt(i));
out.write(bytes);
}
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static byte[] char2byte(char c){
//一个字符串占有两个字节
byte[] bytes = new byte[2];
bytes[0] = (byte) ((c)&0xff);//整数的低八位
bytes[1] = (byte) ((c>>8)&0xff);
return bytes;
}
}
服务器:进行字符串的接收
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serSocket = new ServerSocket(9090);
Socket ser = serSocket.accept();
System.out.println("连接成功");
OutputStream out = ser.getOutputStream();
InputStream input = ser.getInputStream();
while(true){
byte c = (byte) input.read();
byte[] bytes = new byte[c*2];
input.read(bytes);
String s = byte2Str(bytes);
System.out.println("s = "+s);
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String byte2Str(byte[] bytes){
//一个字符串占有两个字节
byte[] bytenow = new byte[2];
String s = "";
int index = 0;
for(int i = 0;i<bytes.length;i++){
bytenow[index++] = bytes[i];
if(index == 2){
s = s + byte2char(bytenow);
index = 0;
}
}
return s;
}
public static char byte2char(byte c[]){
char c1=(char) ((c[1]&0xff)<<8);
char c2=(char) ((c[0]&0xff)<<0);
return (char) (c1+c2);
}
}
方法二
客户端:
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",9090);
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
String s = "吃hhhh";
byte c = (byte) s.getBytes().length;
out.write(c);
System.out.println("c = "+c);
out.write(s.getBytes());
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static byte[] char2byte(char c){
//一个字符串占有两个字节
byte[] bytes = new byte[2];
bytes[0] = (byte) ((c)&0xff);//整数的低八位
bytes[1] = (byte) ((c>>8)&0xff);
return bytes;
}
}
服务器端:
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serSocket = new ServerSocket(9090);
Socket ser = serSocket.accept();
System.out.println("连接成功");
OutputStream out = ser.getOutputStream();
InputStream input = ser.getInputStream();
while(true){
byte c = (byte) input.read();
byte[] bytes = new byte[c];
input.read(bytes);
String s = new String(bytes);
System.out.println("s = "+s);
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这种方法利用系统自带的方法,简洁方便。
转换原理:
- 字符串是由一个个字符构成的,对于中文英文都可以用一个字符进行存储。
- 一个字符占用两个字节,所以将我们的字符转换成一个大小为2的字节数组,将其写入数据
(注意:在写入字符之前先写入字符串的长度)
public static byte[] char2byte(char c){
//一个字符串占有两个字节
byte[] bytes = new byte[2];
bytes[0] = (byte) ((c)&0xff);//整数的低八位
bytes[1] = (byte) ((c>>8)&0xff);
return bytes;
}
- 字符串的长度在服务器端发挥作用,我们根据收到的字符串长度,建立一个大小为其2倍的字节数组,读入数据。
public static String byte2Str(byte[] bytes){
//一个字符串占有两个字节
byte[] bytenow = new byte[2];
String s = "";
int index = 0;
for(int i = 0;i<bytes.length;i++){
bytenow[index++] = bytes[i];
if(index == 2){
s = s + byte2char(bytenow);
index = 0;
}
}
return s;
}
遇到问题:
这种转换的方式,我一开始写的时候很成功,但后面代码丢失,找不到了。可我一直想用这种方法,就继续尝试写,总是陷入困境。原因就是我开始的思维被局限掉了,我直接把字符串转为字节进行发送,但是它是3个字节一个中文字符,1个字节英文字符,就非常混乱,转换的时候也遇到问题,真的好悲伤。其实真正的做法是,需要一个个字符拆分成字节后发送,那边再接收。
写入图片
public void sendImage(OutputStream out,BufferedImage image){
try {
int[][] imgdata = toArray(image);
out.write((byte)4);//从读信息得到fristb,说明out不为空
byte[] imgw = divide(imgdata.length);//图片一个一维数组的长度
byte[] imgh = divide(imgdata[0].length);//图片一维数组的个数
out.write(imgw);//将图片一个一维数组的长度发送出去
out.write(imgh);//将图片一维数组的个数发送出去
for(int i = 0;i<imgdata.length;i++){
for(int j = 0;j<imgdata[i].length;j++){
byte[] writeByte = divide(imgdata[i][j]);
out.write(writeByte);//这里写入也是字节
}
}
out.write((byte)13);
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
}//输出短写入数据(发送数据
}
public void getImage(InputStream input,Graphics videog) throws IOException {
byte[] imgw = new byte[4];
input.read(imgw);
int w = combine(imgw);
byte[] imgh = new byte[4];
input.read(imgh);
int h = combine(imgh);//
//初始化图片数组
BufferedImage image = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
Graphics gnow = image.getGraphics();
for(int i = 0;i<w;i++){
for(int j = 0;j<h;j++){
byte[] get = new byte[4];
try {
input.read(get);
gnow.setColor(new Color(combine(get)));
gnow.drawLine(i, j, i, j);
// gnow.fillRect(i, j, 2, 2);
} catch (IOException e) {
e.printStackTrace();
}
}
}
videog.drawImage(image, 0, 0, null);
}
发送原理:
- 图片相当于一个二维数组,我们的信息有位置和颜色,所以可以获取位置后得到颜色,在画布上画出来即可。
- 发送的时候,需要发送图片的宽度与高度,以便读取数据的时候建立一个相应大小的二维数组。
- 利用双缓冲绘图即可以使图片更好的展现出来