HTTP手动客户端未正确写入磁盘JAVA
我正在尝试构建一个手动HTTP客户端(使用套接字)和一个缓存,但我似乎不明白为什么文件没有正确保存到磁盘。它对HTML文件非常有效,但对于其他不基于文本的文件类型(如.gif)似乎不起作用。谁能告诉我为什么?一般来说,我对HTTP协议和套接字编程相当陌生 获取响应的循环HTTP手动客户端未正确写入磁盘JAVA,java,sockets,http,file-io,Java,Sockets,Http,File Io,我正在尝试构建一个手动HTTP客户端(使用套接字)和一个缓存,但我似乎不明白为什么文件没有正确保存到磁盘。它对HTML文件非常有效,但对于其他不基于文本的文件类型(如.gif)似乎不起作用。谁能告诉我为什么?一般来说,我对HTTP协议和套接字编程相当陌生 获取响应的循环 InputStream inputStream = socket.getInputStream(); PrintWriter outputStream = new PrintWriter(socket.getOu
InputStream inputStream = socket.getInputStream();
PrintWriter outputStream = new PrintWriter(socket.getOutputStream());
ArrayList<Byte> dataIn = new ArrayList<Byte>();
ArrayList<String> stringData = new ArrayList<String>();
//Indices to show the location of certain lines in arrayList
int blankIndex = 8;
int lastModIndex = 0;
int byteBlankIndex = 0;
try
{
//Get last modified date
long lastMod = getLastModified(url);
Date d = new Date(lastMod);
//Construct the get request
outputStream.print("GET "+ "/" + pathName + " HTTP/1.1\r\n");
outputStream.print("If-Modified-Since: " + ft.format(d)+ "\r\n");
outputStream.print("Host: " + hostString+"\r\n");
outputStream.print("\r\n");
outputStream.flush();
//Booleans to prevent duplicates, only need first occurrences of key strings
boolean blankDetected = false;
boolean lastModDetected = false;
//Keep track of current index
int count = 0;
int byteCount = 0;
//While loop to read response
String buff = "";
byte t;
while ( (t = (byte) inputStream.read()) != -1)
{
dataIn.add(t);
//Check for key lines
char x = (char) t;
buff = buff + x;
//For the first blank line (signaling the end of the header)
if(x == '\n')
{
stringData.add(buff);
if(buff.equals("\r\n") && !blankDetected)
{
blankDetected = true;
blankIndex = count;
byteBlankIndex = byteCount + 2;
}
//For the last modified line
if(buff.contains("Last-Modified:") && !lastModDetected)
{
lastModDetected = true;
lastModIndex = count;
}
buff = "";
count++;
}
//Increment count
byteCount++;
}
}
InputStream InputStream=socket.getInputStream();
PrintWriter outputStream=新的PrintWriter(socket.getOutputStream());
ArrayList dataIn=新的ArrayList();
ArrayList stringData=新的ArrayList();
//显示arrayList中某些行的位置的索引
int blankIndex=8;
int lastModIndex=0;
int-byteBlankIndex=0;
尝试
{
//获取上次修改日期
long lastMod=getLastModified(url);
日期d=新日期(lastMod);
//构造get请求
print(“获取“+”/“+pathName+”HTTP/1.1\r\n”);
outputStream.print(“如果自:“+ft.format(d)+”\r\n”起修改);
打印(“主机:“+hostString+”\r\n”);
outputStream.print(“\r\n”);
outputStream.flush();
//布尔值为防止重复,只需要首先出现键字符串
布尔blankDetected=false;
布尔lastModDetected=false;
//跟踪当前索引
整数计数=0;
int字节数=0;
//While循环读取响应
字符串buff=“”;
字节t;
而((t=(字节)inputStream.read())!=-1)
{
数据输入。添加(t);
//检查关键线路
char x=(char)t;
buff=buff+x;
//对于第一个空行(表示页眉结束)
如果(x=='\n')
{
stringData.add(buff);
if(buff.equals(“\r\n”)&&&!blankDetected)
{
blankDetected=true;
空白指数=计数;
字节索引=字节计数+2;
}
//对于最后修改的行
if(buff.contains(“上次修改:”)&&!lastModDetected)
{
lastModDetected=true;
lastModIndex=计数;
}
buff=“”;
计数++;
}
//增量计数
字节计数++;
}
}
代码通过响应解析并将文件写入磁盘
String catalogKey = hostString+ "/" + pathName;
//Get the directory sequence to make
String directoryPath = catalogKey.substring(0, catalogKey.lastIndexOf("/") + 1);
//Make the directory sequence if possible, ignore the boolean value that results
boolean ignoreThisBooleanVal = new File(directoryPath).mkdirs();
//Setup output file, and then write the contents of dataIn (excluding header) to the file
PrintWriter output = new PrintWriter(new FileWriter(new File(catalogKey)),true);
for(int i = byteBlankIndex + 1 ; i < dataIn.size(); i++)
{
output.print(new String(new byte[]{ (byte)dataIn.get(i)}, StandardCharsets.UTF_8));
}
output.close();
String catalogKey=hostString+“/”+路径名;
//获取要生成的目录序列
String directoryPath=catalogKey.substring(0,catalogKey.lastIndexOf(“/”)+1);
//如果可能,设置目录序列,忽略结果的布尔值
boolean ignoreThisBooleanVal=新文件(directoryPath).mkdirs();
//设置输出文件,然后将dataIn(不包括标头)的内容写入该文件
PrintWriter输出=新的PrintWriter(新的FileWriter(新文件(catalogKey)),true);
对于(inti=byteBlankIndex+1;i
问题就在这里。应改为:
int t;
while ( (t = inputStream.read()) != -1)
{
byte b = (byte)t;
// use b from now on in the loop.
问题是输入中的0xff
字节将返回到int
作为0xff
,但返回到byte
作为-1,因此您无法将其与流结束区分开
您应该使用文件输出流,
而不是文件编写器
,并且您不应该将潜在的二进制数据累积到字符串
或字符串缓冲区
或与字符
有关的任何内容。一旦到达头的末尾,就应该打开一个FileOutputStream
,然后开始复制字节。使用缓冲流使所有这一切更加有效
在这些代码中没有太多的地方指出<代码> HTTURLCONNECT/<代码>已经存在。
因为你正在把一个字节转换成一个字符,这对于二进制数据流是不起作用的。如果我把它保留为一个字节,那么即使在一个HTML文件中,在修复空白字节索引计数器之后,也会得到一系列的数字,它工作得很完美。int t;
while ( (t = inputStream.read()) != -1)
{
byte b = (byte)t;
// use b from now on in the loop.