二进制文件类型检测代码问题:JPG识别失败且输出多字节异常
Let's break down why your code isn't recognizing JPG files and why you're seeing those ffffff values in the output:
Root Cause 1: Signed Char Sign Extension
Your buffer is declared as char buffer[8];. On most compilers, char is a signed type. When you read a byte like 0xFF (part of the JPG header), it's stored as -1 in a signed char. When passed to printf with the %x format specifier, this value is promoted to int, and since it's negative, it gets sign-extended to 0xFFFFFFFF—hence the ffffff in your output.
Fix: Use Unsigned Char for the Buffer
Change the buffer declaration to:
unsigned char buffer[8];
This ensures all bytes are treated as positive values, so 0xFF will print as ff instead of ffffff.
Root Cause 2: Incorrect Header Matching Logic
Your inner loop checks if header[i][j] != buffer[j] before checking if header[i][j] == 0x00. For the JPG entry ({0xFF,0xD8,0x00,...}), this means when j=2, the code first checks if 0x00 != buffer[2] (which is true for almost all JPG files, since the third byte is 0xFF), so it breaks the loop and moves to the next file type. It never reaches the wildcard check to declare a match.
Fix: Reorder the Checks in the Inner Loop
The wildcard logic (using 0x00 to mean "stop checking") needs to come before the mismatch check. Additionally, we need to handle cases where the header uses all 8 bytes (like PNG) by verifying if we've completed all checks.
Root Cause 3: Unchecked File Read
Your code doesn't verify if fread successfully read all 8 bytes. If the file is shorter than 8 bytes, this can lead to undefined behavior when accessing uninitialized parts of the buffer.
Fix: Check the Return Value of fread
Add a check after fread to ensure we read the full 8 bytes:
if (fread(buffer, sizeof(buffer), 1, fd) != 1) { printf("Error reading file or file is too small\n"); fclose(fd); return -1; }
Full Corrected Code
#include <stdio.h> const int header[6][8] = { {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A}, {0xFF,0xD8,0x00,0x00,0x00,0x00,0x00,0x00}, {0xFF,0xFB,0x00,0x00,0x00,0x00,0x00,0x00}, {0x49,0x44,0x33,0x00,0x00,0x00,0x00,0x00}, {0x25,0x50,0x44,0x46,0x2D,0x00,0x00,0x00}, {0x42,0x4C,0x45,0x4E,0x44,0x45,0x52,0x00} }; const char* filetype[6] = {"PNG","JPG","MP3","MP3v2","PDF","Blender"}; int main() { FILE *fd; unsigned char buffer[8]; // Fixed to unsigned char if ((fd = fopen("C:\\Users\\***\\Desktop\\Unnamed.jpg", "rb")) == NULL) { printf("Failed to open file\n"); return -1; } // Verify we read all 8 bytes if (fread(buffer, sizeof(buffer), 1, fd) != 1) { printf("Error reading file or file is too small\n"); fclose(fd); return -1; } for (int i = 0; i < 6; i++) { int match = 1; for(int j = 0; j < 8; j++){ printf("Header[%d][%d]: %x\n", i, j, header[i][j]); printf("Buffer[%d]: %x\n", j, buffer[j]); // Handle wildcard first if (header[i][j] == 0x00) { printf("Found file type: %s\n", filetype[i]); fclose(fd); return 1; } // Check for mismatch if (header[i][j] != buffer[j]) { match = 0; break; } } // If all 8 bytes matched (no wildcard hit) if (match) { printf("Found file type: %s\n", filetype[i]); fclose(fd); return 1; } } printf("Couldn't determine filetype - Not in library\n"); fclose(fd); // Don't forget to close the file return 0; }
Key Takeaways
- Use
unsigned charfor raw binary data to avoid sign extension issues. - Always validate input operations like
freadto ensure you're working with valid data. - Order logic checks correctly to implement wildcard matching as intended.
- Close files when done to avoid resource leaks.
内容的提问来源于stack exchange,提问作者Avinta

