我一直在尝试使用Java Socket实现一个简单的http客户端。在我的程序中,我从服务器请求图像并尝试在本地计算机上复制请求的JPEG图像。我已设法构建请求并收到所需的内容。我还将响应头和内容分开了。但问题是当我使用FileOutputStream
将字节写入.jpeg文件时,在写入图像查看器(如picasa)中打开文件后,图像似乎无效。
这是我的整个代码。
任何人都可以告诉我代码有什么问题吗?为什么图像无效?
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import sun.misc.IOUtils;
public class ImageCopy {
public static void main(String args[]) throws IOException{
String host = "www.uni-koblenz-landau.de"; //declare the host name
String resourceLoc = "/images/starts-c-ko.jpg"; //declare the specific pagename of get
HttpRequester req = new HttpRequester();
req.request(host, resourceLoc); //send the request mentiong the host and pagename
}
}
class HttpRequester{
public void request(String host, String resourceLoc) throws IOException{
Socket httpSocket = new Socket(host, 80); //create the request for port 80
PrintWriter writer = new PrintWriter(httpSocket.getOutputStream());
FileOutputStream foutStream = new FileOutputStream("E:\\quora.jpeg"); //creating file to hold the output stream
// building the header fields
String protocol = "GET /" +resourceLoc+" HTTP/1.1";
String connection ="Connection: close";
String acceptedLanguage ="Accept-Language: de,en;q=0.7,en-us;q=0.3";
String headerEnd = "";
String HostHeader = "Host: www.uni-koblenz-landau.de";
// writing the headers to the outputstream
writer.println(protocol);
writer.println(HostHeader);
writer.println(connection);
writer.println(acceptedLanguage);
writer.println(headerEnd);
writer.flush();
// request sent
BufferedInputStream reader = new BufferedInputStream(httpSocket.getInputStream());
InputStream is;
int byteCode =0;
char ch ;
StringBuilder builder = new StringBuilder();
while((byteCode=reader.read())!=-1)
{
builder.append((char)byteCode);
// System.out.print((char)byteCode);
}
String text = builder.toString();
// sub[0] is supposed to contain the header and sub[1] should contain the bytes of the image
String[] sub = text.split("\r\n\r\n");
System.out.println(sub[0]);
byte[] byts = sub[1].getBytes();
for(int i=0;i<byts.length;i++){
foutStream.write(byteCode);
}
System.out.println(byts.length);
}
}
答案 0 :(得分:1)
请先尝试以下工作代码:
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLTest {
private static void sendGet() throws Exception {
String url = "http://www.uni-koblenz-landau.de/images/starts-c-ko.jpg";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
InputStream in = con.getInputStream();
OutputStream out = new FileOutputStream("/Users/ravikiran/Desktop/abc.jpg");
try {
byte[] bytes = new byte[2048];
int length;
while ((length = in.read(bytes)) != -1) {
out.write(bytes, 0, length);
}
} finally {
in.close();
out.close();
}
}
public static void main(String[] args) throws Exception {
sendGet();
}
}
答案 1 :(得分:0)
显示的代码中至少有2个问题。首先是微不足道的,接近你的计划结束:
byte[] byts = sub[1].getBytes();
for(int i=0;i<byts.length;i++){
foutStream.write(byteCode);
}
我认为foutStream.write(byts[i]);
应该更好。
第二个更微妙。你得到字节,在字符串构建器中将它们转换为char
,然后将它们作为字节返回。对于字节值&gt; = 128,这不能正常工作。
我刚做了这个小测试:
public class ByteCharTest {
@Test
public void test1() {
byte[] bytes = new byte[]{ 'x', (byte) 0xc3, (byte) 0xa9,
(byte) 0xc3, (byte) 0xa8, 'y', (byte) 0xe9, (byte) 0xe8, 'z'};
StringBuilder sb = new StringBuilder();
for(byte b: bytes) {
sb.append((char) b);
}
String s = sb.toString();
byte[] byte2 = s.getBytes();
assertEquals(bytes.length, byte2.length);
for(int i=0; i<bytes.length; i++) {
assertEquals(bytes[i], byte2[i]);
}
}
}
它打破了。在调试器下,字符串s是&#34; x \ uffce \ uffa9 \ uffc3 \ uffa9y \ uffe9 \ uffe8z&#34;因为从byte到char传播的符号位和byte2的转换是x????y??z
如果StringBuilder
被提供,则测试有效:
sb.append((char) (((int) b) && 0xff));
所以在你的代码中,你应该有:
while((byteCode=reader.read())!=-1)
{
builder.append((char) (((int) byteCode) && 0xff));
// System.out.print((char)byteCode);
}
为了解释测试的字节,0xc3 0xa9
和0xc3 0xa8
是éè
的UTF-8代码,而0xe8 0xe9
是éè
的Latin1代码...
答案 2 :(得分:-1)
实际适合您问题的解决方案:
// Initialize the stream.
final InputStream inputStream = socket.getInputStream();
// Header end flag.
boolean headerEnded = false;
byte[] bytes = new byte[2048];
int length;
while ((length = inputStream.read(bytes)) != -1) {
// If the end of the header had already been reached, write the bytes to the file as normal.
if (headerEnded)
foutStream.write(bytes, 0, length);
// This locates the end of the header by comparing the current byte as well as the next 3 bytes
// with the HTTP header end "\r\n\r\n" (which in integer representation would be 13 10 13 10).
// If the end of the header is reached, the flag is set to true and the remaining data in the
// currently buffered byte array is written into the file.
else {
for (int i = 0; i < 2045; i++) {
if (bytes[i] == 13 && bytes[i + 1] == 10 && bytes[i + 2] == 13 && bytes[i + 3] == 10) {
headerEnded = true;
foutputStream.write(bytes, i+4, 2048-i-4);
break;
}
}
}
}
inputStream.close();
foutStream.close();