Java 如何膨胀git树对象?

Java 如何膨胀git树对象?,java,git,hash,Java,Git,Hash,我正在做一些Java类来从Git对象读取信息。每个类都以相同的方式工作:使用repo路径和散列检索文件,然后打开、膨胀并每次读取一行。这对blob和提交非常有效,但不知何故,膨胀对树对象不起作用 我用来读取文件的代码在任何地方都是一样的: FileInputStream fis = new FileInputStream(path); InflaterInputStream inStream = new InflaterInputStream(fis); BufferedReader bf =

我正在做一些Java类来从Git对象读取信息。每个类都以相同的方式工作:使用repo路径和散列检索文件,然后打开、膨胀并每次读取一行。这对blob和提交非常有效,但不知何故,膨胀对树对象不起作用

我用来读取文件的代码在任何地方都是一样的:

FileInputStream fis = new FileInputStream(path);
InflaterInputStream inStream = new InflaterInputStream(fis);
BufferedReader bf = new BufferedReader(new InputStreamReader(inStream));
它对树旁边的每个对象都没有问题。当我试着以这种方式阅读一棵树时,我得到了以下结论:

tree 167100644 README.mdDRwJiU��#�%?^>n��40000 dir1*�j4ކ��K-�������100644 file1�⛲��CK�)�wZ���S�100644 file2�⛲��CK�)�wZ���S�100644 file4�⛲��CK�)�wZ���S�

似乎文件名和八进制模式的解码方式是正确的,而散列则不是(我用上述代码解码其他散列时没有任何问题)。树对象中散列的编码与其他git对象中散列的编码有什么区别吗?

OID存储在树中,而不是作为文本,因此标题中对您的问题的回答是“您已经在做了”,而文本中对您的问题的回答是“是”

回答一个问题:为什么这样做?接下来,它有好的一面和坏的一面,你碰到了坏的一面。谈论这一点没什么意义,任何改变这一决定的痛苦/收益比率都将是可怕的

每次读一行


不要那样做。存储作为二进制调用的一个好处是,它打破了依赖于永远不会遇到嵌入换行符的代码,比其他情况下快得多。我建议“如果您误用或误解了它,它应该尽可能快地破坏”,这是一条优秀的设计规则,与“发送的内容要保守,接受的内容要自由”。

OID原始存储在树中,而不是文本中,因此标题中提出的问题的答案是“您已经在做了”,你的问题在课文中的答案是“是的。”

回答一个问题:为什么这样做?接下来,它有好的一面和坏的一面,你碰到了坏的一面。谈论这一点没什么意义,任何改变这一决定的痛苦/收益比率都将是可怕的

每次读一行


不要那样做。存储作为二进制调用的一个好处是,它打破了依赖于永远不会遇到嵌入换行符的代码,比其他情况下快得多。我建议“如果您误用或误解了它,它应该尽可能快地破坏”,这是一条优秀的设计规则,与“发送的内容要保守,接受的内容要自由”一样值得遵循(文档中没有这么清楚)。文件的大部分是用ASCII编码的,这意味着它可以用任何你喜欢的方式读取,但是散列没有编码,它们只是原始字节

由于有两种不同的编码,最好的解决方案是逐字节读取文件,记住文件的位置

我的解决方案(我只对内容的名称和散列感兴趣,所以剩下的就扔掉了):

FileInputStream fis=新的FileInputStream(this.filepath);
充气器输入气流内=新的充气器输入气流(fis);
int i=-1;
而((i=inStream.read())!=0){
//一线
}
//内容数据
而((i=inStream.read())!=-1){
而((i=inStream.read())!=0x20){//0x20是空间字符
//权限字节
}
//文件名:0-终止
字符串filename=“”;
而((i=inStream.read())!=0){
文件名+=(字符)i;
}
//哈希:20字节长,可以包含任何值,唯一的方法
//要确定的是要计算字节数
字符串哈希=”;
用于(int count=0;count<20;count++){
i=流内读取();
hash+=Integer.toHexString(i);
}
}

问题的核心在于git树文件中有两种编码方式(文档中没有这么清楚)。大部分文件都是用ASCII编码的,这意味着它可以用任何你喜欢的方式读取,但哈希没有编码,它们只是原始字节

由于有两种不同的编码,最好的解决方案是逐字节读取文件,记住文件的位置

我的解决方案(我只对内容的名称和散列感兴趣,所以剩下的就扔掉了):

FileInputStream fis=新的FileInputStream(this.filepath);
充气器输入气流内=新的充气器输入气流(fis);
int i=-1;
而((i=inStream.read())!=0){
//一线
}
//内容数据
而((i=inStream.read())!=-1){
而((i=inStream.read())!=0x20){//0x20是空间字符
//权限字节
}
//文件名:0-终止
字符串filename=“”;
而((i=inStream.read())!=0){
文件名+=(字符)i;
}
//哈希:20字节长,可以包含任何值,唯一的方法
//要确定的是要计算字节数
字符串哈希=”;
用于(int count=0;count<20;count++){
i=流内读取();
hash+=Integer.toHexString(i);
}
}

您可能需要二进制IO类才能正确执行此操作您可能需要二进制IO类才能正确执行此操作,因此我应该在某个时间读取一个字符?您的答案不太清楚问题是什么…因此我应该在某个时间读取一个字符?您的答案不太清楚问题是什么。。。
  FileInputStream fis = new FileInputStream(this.filepath);
  InflaterInputStream inStream = new InflaterInputStream(fis);
  int i = -1;
  while((i = inStream.read()) != 0){
      //First line
  }

  //Content data
  while((i = inStream.read()) != -1){
    while((i = inStream.read()) != 0x20){ //0x20 is the space char
      //Permission bytes
    }

    //Filename: 0-terminated
    String filename = "";
    while((i = inStream.read()) != 0){
      filename += (char) i;
    }

    //Hash: 20 byte long, can contain any value, the only way
    // to be sure is to count the bytes
    String hash = "";
    for(int count = 0; count < 20 ; count++){
      i = inStream.read();
      hash += Integer.toHexString(i);
    }
  }