HTTP手动客户端未正确写入磁盘JAVA

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

我正在尝试构建一个手动HTTP客户端(使用套接字)和一个缓存,但我似乎不明白为什么文件没有正确保存到磁盘。它对HTML文件非常有效,但对于其他不基于文本的文件类型(如.gif)似乎不起作用。谁能告诉我为什么?一般来说,我对HTTP协议和套接字编程相当陌生

获取响应的循环

    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.