Hex dump: Difference between revisions
Content deleted Content added
J draft |
m Minor code improvement. |
||
(21 intermediate revisions by 9 users not shown) | |||
Line 1:
{{
A [[wp:Hex_dump|hex dump]] is a textual representation of bytes in a file, and ''hexdump'' is a command-line tool that can dump bytes from a file in a variety of formats, including [[wp:Hexadecimal|hexadecimal]], [[wp:Octal|octal]] and [[wp:ASCII|ASCII]].
Line 13:
For example, the string "Rosetta Code is a programming chrestomathy site 😀." encoded in [[wp:UTF-16|UTF-16]] (little-endian - the first two bytes are the [[wp:Byte_order_mark|byte order mark]]), displayed in the canonical format is:
<syntaxhighlight lang="hexdump">
00000000 ff fe 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6f 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
Line 22:
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
</syntaxhighlight>
;Task
Line 40:
Implement a binary mode. For this task, in binary mode, the example above should be displayed like this:
<syntaxhighlight lang="hexdump">
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
Line 60:
00000066 00101110 00000000 |..|
00000068
</syntaxhighlight>
Other hexdump/xxd features and a command line interface to your program are optional.
Line 238:
00000066 00101110 00000000 |..|
00000068
</pre>
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <algorithm>
#include <bitset>
#include <cstdint>
#include <filesystem>
#include <format>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
enum DumpType { HEX, XXD };
struct DumpDetails {
DumpType type;
uint32_t factor;
uint32_t block_length;
uint32_t line_length;
};
class Converter {
public:
Converter(const std::vector<uint8_t>& aBytes, const uint32_t& aStart_Index,
const uint32_t& aLength, const DumpDetails& aDump_Details) {
start_index =
std::min(static_cast<uint32_t>(aBytes.size()), std::max(static_cast<uint32_t>(0), aStart_Index));
length = ( aLength < 1 || aLength > aBytes.size() - start_index ) ? aBytes.size() - start_index : aLength;
dump_details = aDump_Details;
std::copy(aBytes.begin() + start_index, aBytes.begin() + start_index + length, std::back_inserter(bytes));
}
std::string to_converted_string() {
std::string result = "";
for ( uint32_t i = 0; i * dump_details.factor < bytes.size(); ++i ) {
result += to_converted_row(byte_vector(i * dump_details.factor, dump_details.factor));
}
return result + to_hex(counter_finish);
}
private:
std::vector<uint8_t> byte_vector(const uint32_t& current_index, const uint32_t& current_length) {
counter_start = current_index;
counter_finish = std::min(static_cast<size_t>(current_index + current_length), bytes.size());
std::vector<uint8_t> subvector(bytes.begin() + current_index, bytes.begin() + counter_finish);
return subvector;
}
std::string to_converted_row(std::vector<uint8_t> row) const {
std::string line, characters;
for ( const uint8_t& byte : row ) {
line += to_digit(byte);
characters += printable_character(byte);
}
line = padding(insertSpace(line));
return to_hex(counter_start) + line + "|" + characters + "|" + "\n";
}
std::string insertSpace(const std::string& line) const {
std::string result = line;
for ( uint8_t i = dump_details.block_length; i < line.size(); i += dump_details.block_length ) {
result.insert(i++, " ");
}
return result;
}
std::string to_digit(const uint32_t& number) const {
std::string result = "";
switch ( dump_details.type ) {
case DumpType::HEX : result = std::format("{:02x}", number & 0xff) + " "; break;
case DumpType::XXD : result = std::bitset<8>(number).to_string(); break;
};
return result;
}
std::string printable_character(const uint32_t& number) const {
return std::string(1, ( number >= 32 && number < 127 ) ? static_cast<char>(number) : '.');
}
std::string padding(const std::string& line) const {
return line + std::string(dump_details.line_length - line.size(), ' ');
}
std::string to_hex(const uint32_t& number) const {
return std::format("{:08x}", number) + " ";
}
uint32_t counter_start = 0, counter_finish = 0;
uint32_t start_index, length;
std::vector<uint8_t> bytes;
DumpDetails dump_details;
};
std::vector<uint8_t> read_file_data(const std::string& file_name) {
std::filesystem::path input_file_path { file_name };
const uint64_t length = std::filesystem::file_size(input_file_path);
if ( length == 0 ) {
return { };
}
std::vector<uint8_t> buffer(length);
std::ifstream input_file(file_name, std::ios_base::binary);
input_file.read(reinterpret_cast<char*>(buffer.data()), length);
input_file.close();
return buffer;
}
int main() {
std::vector<uint8_t> bytes = read_file_data("ExampleUTF16LE.dat");
DumpDetails hex = { DumpType::HEX, 16, 24, 50 };
DumpDetails xxd = { DumpType::XXD, 6, 8, 55 };
std::cout << "Hex dump of the entire file:" << std::endl;
std::cout << Converter(bytes, 0, bytes.size(), hex).to_converted_string() << std::endl << std::endl;
std::cout << "xxd dump of the entire file:" << std::endl;
std::cout << Converter(bytes, 0, bytes.size(), xxd).to_converted_string() << std::endl << std::endl;
std::cout << "Hex dump of the file from byte 20 to byte 94:" << std::endl;
std::cout << Converter(bytes, 20, 75, hex).to_converted_string() << std::endl << std::endl;
std::cout << "xxd dump of the file from byte 38 to byte 58:" << std::endl;
std::cout << Converter(bytes, 38, 21, xxd).to_converted_string() << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
Hex dump of the entire file:
00000000 ff fe 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6f 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
00000020 20 00 61 00 20 00 70 00 72 00 6f 00 67 00 72 00 | .a. .p.r.o.g.r.|
00000030 61 00 6d 00 6d 00 69 00 6e 00 67 00 20 00 63 00 |a.m.m.i.n.g. .c.|
00000040 68 00 72 00 65 00 73 00 74 00 6f 00 6d 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
xxd dump of the entire file:
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
0000000c 01110100 00000000 01100001 00000000 00100000 00000000 |t.a. .|
00000012 01000011 00000000 01101111 00000000 01100100 00000000 |C.o.d.|
00000018 01100101 00000000 00100000 00000000 01101001 00000000 |e. .i.|
0000001e 01110011 00000000 00100000 00000000 01100001 00000000 |s. .a.|
00000024 00100000 00000000 01110000 00000000 01110010 00000000 | .p.r.|
0000002a 01101111 00000000 01100111 00000000 01110010 00000000 |o.g.r.|
00000030 01100001 00000000 01101101 00000000 01101101 00000000 |a.m.m.|
00000036 01101001 00000000 01101110 00000000 01100111 00000000 |i.n.g.|
0000003c 00100000 00000000 01100011 00000000 01101000 00000000 | .c.h.|
00000042 01110010 00000000 01100101 00000000 01110011 00000000 |r.e.s.|
00000048 01110100 00000000 01101111 00000000 01101101 00000000 |t.o.m.|
0000004e 01100001 00000000 01110100 00000000 01101000 00000000 |a.t.h.|
00000054 01111001 00000000 00100000 00000000 01110011 00000000 |y. .s.|
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..|
00000068
Hex dump of the file from byte 20 to byte 94:
00000000 6f 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000010 20 00 70 00 72 00 6f 00 67 00 72 00 61 00 6d 00 | .p.r.o.g.r.a.m.|
00000020 6d 00 69 00 6e 00 67 00 20 00 63 00 68 00 72 00 |m.i.n.g. .c.h.r.|
00000030 65 00 73 00 74 00 6f 00 6d 00 61 00 74 00 68 00 |e.s.t.o.m.a.t.h.|
00000040 79 00 20 00 73 00 69 00 74 00 65 |y. .s.i.t.e|
0000004b
xxd dump of the file from byte 38 to byte 58:
00000000 01110000 00000000 01110010 00000000 01101111 00000000 |p.r.o.|
00000006 01100111 00000000 01110010 00000000 01100001 00000000 |g.r.a.|
0000000c 01101101 00000000 01101101 00000000 01101001 00000000 |m.m.i.|
00000012 01101110 00000000 01100111 |n.g|
00000015
</pre>
Line 429 ⟶ 605:
bindump=: {{
assert. 'literal'-:datatype y
b=. '',~_6(' ',,)\' ',.,/"2":"0(8#2)#:256+a.i.y
a=. '',~_6(' |','|',~])\(y e.32}.127{.a.)}'.',:y
i=. 0 1}.hfd(2^32)+6*i.#b
Line 466 ⟶ 642:
00000070
bindump sample
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
0000000c 01110100 00000000 01100001 00000000 00100000 00000000 |t.a. .|
00000012 01000011 00000000 01101111 00000000 01100100 00000000 |C.o.d.|
00000018 01100101 00000000 00100000 00000000 01101001 00000000 |e. .i.|
0000001e 01110011 00000000 00100000 00000000 01100001 00000000 |s. .a.|
00000024 00100000 00000000 01110000 00000000 01110010 00000000 | .p.r.|
0000002a 01101111 00000000 01100111 00000000 01110010 00000000 |o.g.r.|
00000030 01100001 00000000 01101101 00000000 01101101 00000000 |a.m.m.|
00000036 01101001 00000000 01101110 00000000 01100111 00000000 |i.n.g.|
0000003c 00100000 00000000 01100011 00000000 01101000 00000000 | .c.h.|
00000042 01110010 00000000 01100101 00000000 01110011 00000000 |r.e.s.|
00000048 01110100 00000000 01101111 00000000 01101101 00000000 |t.o.m.|
0000004e 01100001 00000000 01110100 00000000 01101000 00000000 |a.t.h.|
00000054 01111001 00000000 00100000 00000000 01110011 00000000 |y. .s.|
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..|
0000006c
</pre>
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public final class HexDump {
public static void main(String[] args) throws IOException {
byte[] bytes = Files.readAllBytes(Path.of("ExampleUTF16LE.dat"));
System.out.println("Hex dump of the entire file:");
System.out.println( new Converter(bytes, 0, bytes.length, DumpType.HEX).toConvertedString() );
System.out.println();
System.out.println("xxd dump of the entire file:");
System.out.println( new Converter(bytes, 0, bytes.length, DumpType.XXD).toConvertedString() );
System.out.println();
System.out.println("Hex dump of the file from byte 20 to byte 94:");
System.out.println( new Converter(bytes, 20, 75, DumpType.HEX).toConvertedString() );
System.out.println();
System.out.println("xxd dump of the file from byte 38 to byte 58:");
System.out.println( new Converter(bytes, 38, 21, DumpType.XXD).toConvertedString() );
}
private static final class Converter {
public Converter(byte[] aBytes, int aStartIndex, int aLength, DumpType aDumpType) {
startIndex = Math.min(aBytes.length, Math.max(0, aStartIndex));
length = ( aLength < 1 || aLength > aBytes.length - startIndex ) ? aBytes.length - startIndex : aLength;
dumpType = aDumpType;
bytes = IntStream.range(startIndex, startIndex + length).mapToObj( i -> aBytes[i] ).toList();
}
public String toConvertedString() {
return IntStream.iterate(0, i -> i * dumpType.factor < bytes.size(), i -> i + 1)
.mapToObj( i -> byteList(i * dumpType.factor, dumpType.factor) )
.map( list -> toConvertedRow(list) )
.collect(Collectors.joining())
+ toHex(counterFinish);
}
private List<Byte> byteList(int currentIndex, int currentLength) {
counterStart = currentIndex;
counterFinish = Math.min(currentIndex + currentLength, bytes.size());
return bytes.subList(currentIndex, counterFinish);
}
private String toConvertedRow(List<Byte> row) {
String line = row.stream().map( b -> toDigit(b) ).collect(Collectors.joining());
line = padding(insertSpace(line));
return toHex(counterStart) + line + "|" +
row.stream().map( b -> printableCharacter(b) ).collect(Collectors.joining()) + "|" + "\n";
}
private String insertSpace(String line) {
return Pattern.compile(".{1," + dumpType.blockLength + "}")
.matcher(line).results().map(MatchResult::group).collect(Collectors.joining(" "));
}
private String toDigit(int number) {
return switch ( dumpType ) {
case HEX -> String.format("%02x ", number & 0xff);
case XXD -> Integer.toBinaryString( ( 1 << 8 | ( number & 0xff ) ) ).substring(1);
};
}
private String printableCharacter(int number) {
return ( number >= 32 && number < 127 ) ? String.valueOf((char) number) : ".";
}
private String padding(String line) {
return String.format("%1$-" + dumpType.lineLength + "s", line);
}
private String toHex(int number) {
return String.format("%08x ", number);
}
private int counterStart, counterFinish;
private final int startIndex, length;
private final List<Byte> bytes;
private final DumpType dumpType;
}
private static enum DumpType {
HEX(16, 24, 50), XXD(6, 8, 55);
private DumpType(int aFactor, int aBlockLength, int aLineLength) {
factor = aFactor;
blockLength = aBlockLength;
lineLength = aLineLength;
}
private final int factor, blockLength, lineLength;
}
}
</syntaxhighlight>
{{ out }}
<pre>
Hex dump of the entire file:
00000000 ff fe 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6f 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
00000020 20 00 61 00 20 00 70 00 72 00 6f 00 67 00 72 00 | .a. .p.r.o.g.r.|
00000030 61 00 6d 00 6d 00 69 00 6e 00 67 00 20 00 63 00 |a.m.m.i.n.g. .c.|
00000040 68 00 72 00 65 00 73 00 74 00 6f 00 6d 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
xxd dump of the entire file:
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
0000000c 01110100 00000000 01100001 00000000 00100000 00000000 |t.a. .|
00000012 01000011 00000000 01101111 00000000 01100100 00000000 |C.o.d.|
00000018 01100101 00000000 00100000 00000000 01101001 00000000 |e. .i.|
0000001e 01110011 00000000 00100000 00000000 01100001 00000000 |s. .a.|
00000024 00100000 00000000 01110000 00000000 01110010 00000000 | .p.r.|
0000002a 01101111 00000000 01100111 00000000 01110010 00000000 |o.g.r.|
00000030 01100001 00000000 01101101 00000000 01101101 00000000 |a.m.m.|
00000036 01101001 00000000 01101110 00000000 01100111 00000000 |i.n.g.|
0000003c 00100000 00000000 01100011 00000000 01101000 00000000 | .c.h.|
00000042 01110010 00000000 01100101 00000000 01110011 00000000 |r.e.s.|
00000048 01110100 00000000 01101111 00000000 01101101 00000000 |t.o.m.|
0000004e 01100001 00000000 01110100 00000000 01101000 00000000 |a.t.h.|
00000054 01111001 00000000 00100000 00000000 01110011 00000000 |y. .s.|
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..|
00000068
Hex dump of the file from byte 20 to byte 94:
00000000 6f 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000010 20 00 70 00 72 00 6f 00 67 00 72 00 61 00 6d 00 | .p.r.o.g.r.a.m.|
00000020 6d 00 69 00 6e 00 67 00 20 00 63 00 68 00 72 00 |m.i.n.g. .c.h.r.|
00000030 65 00 73 00 74 00 6f 00 6d 00 61 00 74 00 68 00 |e.s.t.o.m.a.t.h.|
00000040 79 00 20 00 73 00 69 00 74 00 65 |y. .s.i.t.e|
0000004b
xxd dump of the file from byte 38 to byte 58:
00000000 01110000 00000000 01110010 00000000 01101111 00000000 |p.r.o.|
00000006 01100111 00000000 01110010 00000000 01100001 00000000 |g.r.a.|
0000000c 01101101 00000000 01101101 00000000 01101001 00000000 |m.m.i.|
00000012 01101110 00000000 01100111 |n.g|
00000015
</pre>
=={{header|JavaScript}}==
<syntaxhighlight lang="javascript">
// Generate UTF-16 LE bytes from a string.
function* utf16leBytes(str) {
// Little endian byte order mark.
yield 0xff;
yield 0xfe;
// Iterate code units.
let code_unit;
for (let i = 0; i < str.length; i++) {
code_unit = str.charCodeAt(i);
yield code_unit & 0xff;
yield code_unit >>> 8;
}
}
/**
* Generate sequences of length {@link n} from items in iterable {@link it}.
*/
function* groupBy(it, n) {
let chunk = [];
for (const item of it) {
chunk.push(item);
if (chunk.length == n) {
yield chunk;
chunk = [];
}
}
if (chunk.length) {
yield chunk;
}
}
/**
* @callback Formatter
* @param {Array<number>} chunk
* @returns {string} {@link chunk} formatted for output on one line.
*/
function canonicalFormatter(chunk) {
const bytesAsHex = chunk.map((byte) => byte.toString(16).padStart(2, "0"));
const hex = `${bytesAsHex.slice(0, 8).join(" ")} ${bytesAsHex
.slice(8)
.join(" ")}`.padEnd(48, " ");
const ascii = chunk
.map((byte) => (byte > 31 && byte < 127 ? String.fromCharCode(byte) : "."))
.join("");
return `${hex} |${ascii}|`;
}
/**
* @callback Formatter
* @param {Array<number>} chunk
* @returns {string} {@link chunk} formatted for output on one line.
*/
function binaryFormatter(chunk) {
const bits = chunk
.map((byte) => byte.toString(2).padStart(8, "0"))
.join(" ")
.padEnd(53, " ");
const ascii = chunk
.map((byte) => (byte > 31 && byte < 127 ? String.fromCharCode(byte) : "."))
.join("");
return `${bits} |${ascii}|`;
}
/**
* Generate a textual representation of bytes in {@link data} one line at a time.
*
* @param {Iterable<number>} data
* @param {number} skip
* @param {number} length
* @param {Formatter} formatter
* @param {number} chunkSize
*/
function* hexDumpLines(
data,
skip = 0,
length = Infinity,
formatter = canonicalFormatter,
chunkSize = 16
) {
const it = data[Symbol.iterator]();
for (let i = 0; i < skip; i++) {
it.next();
}
let offset = skip;
let byteCount = 0;
let line = "";
for (let chunk of groupBy(data, chunkSize)) {
// Discard excess bytes if we've overshot length.
if (byteCount + chunk.length > length) {
chunk = chunk.slice(0, length - byteCount);
}
line = formatter(chunk);
yield `${offset.toString(16).padStart(8, "0")} ${line}`;
offset += chunkSize;
byteCount += chunk.length;
if (byteCount >= length) {
break;
}
}
// Final byte count
yield (byteCount + skip).toString(16).padStart(8, "0");
}
/**
* Log a hex dump of {@link data} to the console.
*
* @param {Iterable<number>} data
* @param {number} skip
* @param {number} length
* @param {Formatter} formatter
* @param {number} chunkSize
*/
function consoleHexDump(
data,
skip = 0,
length = Infinity,
formatter = canonicalFormatter,
chunkSize = 16
) {
for (const line of hexDumpLines(data, skip, length, formatter, chunkSize)) {
console.log(line);
}
}
const exampleData = "Rosetta Code is a programming chrestomathy site 😀.";
consoleHexDump(utf16leBytes(exampleData));
console.log("");
consoleHexDump(utf16leBytes(exampleData), 20, 25);
console.log("");
consoleHexDump(utf16leBytes(exampleData), 0, Infinity, binaryFormatter, 6);
</syntaxhighlight>
{{out}}
<pre>
00000000 ff fe 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6f 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
00000020 20 00 61 00 20 00 70 00 72 00 6f 00 67 00 72 00 | .a. .p.r.o.g.r.|
00000030 61 00 6d 00 6d 00 69 00 6e 00 67 00 20 00 63 00 |a.m.m.i.n.g. .c.|
00000040 68 00 72 00 65 00 73 00 74 00 6f 00 6d 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
00000014 6f 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000024 20 00 70 00 72 00 6f 00 67 | .p.r.o.g|
0000002d
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
0000000c 01110100 00000000 01100001 00000000 00100000 00000000 |t.a. .|
00000012 01000011 00000000 01101111 00000000 01100100 00000000 |C.o.d.|
00000018 01100101 00000000 00100000 00000000 01101001 00000000 |e. .i.|
0000001e 01110011 00000000 00100000 00000000 01100001 00000000 |s. .a.|
00000024 00100000 00000000 01110000 00000000 01110010 00000000 | .p.r.|
0000002a 01101111 00000000 01100111 00000000 01110010 00000000 |o.g.r.|
00000030 01100001 00000000 01101101 00000000 01101101 00000000 |a.m.m.|
00000036 01101001 00000000 01101110 00000000 01100111 00000000 |i.n.g.|
0000003c 00100000 00000000 01100011 00000000 01101000 00000000 | .c.h.|
00000042 01110010 00000000 01100101 00000000 01110011 00000000 |r.e.s.|
00000048 01110100 00000000 01101111 00000000 01101101 00000000 |t.o.m.|
0000004e 01100001 00000000 01110100 00000000 01101000 00000000 |a.t.h.|
00000054 01111001 00000000 00100000 00000000 01110011 00000000 |y. .s.|
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..|
00000068
</pre>
=={{header|Julia}}==
<syntaxhighlight lang="julia">function baseddump(io::IO, data::Vector{UInt8}; base = 16, offset = 0, len = -1, displayadjust = 0)
@assert 2 <= base <= 16 "display base $base not supported"
bytes = data[begin+offset:
fullchunksize = base == 16 ? 16 : base > 8 ? 10 : base > 4 ? 8 : 6
padsize = base == 16 ? 2 : base == 2 ? 8 : base > 7 ? 3 : base > 3 ? 4 : 5
Line 505 ⟶ 1,026:
end
s2 = prod(map(n -> n < 128 && isprint(Char(n)) ? Char(n) : '.', chunk))
println(io, string(pos, base = 16, pad = 8) * " " * rpad(s1, vl) * "|" * s2 * "|")
pos += chunklen
end
println(io, string(pos - offset - displayadjust, base = 16, pad = 8))
end
function baseddump(data; base = 16, offset = 0, len = -1)
Line 594 ⟶ 1,115:
=={{header|Phix}}==
<!--
<syntaxhighlight lang="phix">
with javascript_semantics
sequence utf16 = #FEFF & "Rosetta Code is a programming chrestomathy site " & {#d83d,#DE00,'.'}
function to2(integer i) return {and_bits(i,#FF),floor(i/#100)} end function
constant string s = flatten(apply(utf16,to2),"")
--or: (javascript incompatible)
--constant string s = get_text(filename) -- (if you have a suitable premade one to hand)
procedure hexdump(string s, integer start=0, finish=-1, bool bHex=true, bFinalSize=true)
s = s[start+1..finish]
integer ll = iff(bHex?16:6), ls = length(s)
string hbfmt = iff(bHex?"%02x ":"%08b "),
lnfmt = "%08x %s |%-" & sprintf("%d",ll) & "s|\n"
sequence lines = split_by(s,ll)
for l in lines do
string hb = " ", ascii = ""
for i,b in l do
hb &= sprintf(hbfmt,b)
if b<' ' or b>'~' then b = '.' end if
ascii &= b
if i=8 then hb &= ' ' end if
end for
hb = pad_tail(hb,iff(bHex?50:55))
printf(1,lnfmt,{start,hb,ascii})
start += length(l)
end for
if bFinalSize then
printf(1,"%08x\n",{ls})
end if
end procedure
printf(1,"Hexadecimal:\n")
hexdump(s)
printf(1,"\nBinary:\n")
hexdump(s,bHex:=false)
</syntaxhighlight>
Although not shown, the intention is the outer calling code (last four lines) could call hexdump() to display one page at a time, with appropriate user input, and/or read s in chunks and pass a file offset instead of or as well as start, finish.
{{out}}
Line 662 ⟶ 1,184:
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |.. |
00000068
</pre>
=={{header|PHP}}==
<syntaxhighlight lang="php"><?php
// Output the contents of a file (or part of a file) in either hexadecimal or binary
function dump($filename, $mode, $offset=0, $length=null) {
$data = file_get_contents($filename, false, null, $offset, $length);
$c = '';
$h = '';
$a = $offset;
$output = '<pre>';
if ($mode == 'h') {
$linesize = 16;
for ($i = 0; $i < strlen($data); $i++) {
$x = substr($data, $i, 1);
$h .= bin2hex($x) . ' ';
if ($i % 8 == 7) {
$h .= ' ';
}
if (ord($x) >= 32 && ord($x) <= 126) {
$c .= $x;
}
else {
$c .= '.';
}
if ($i % $linesize == 15 || $i == strlen($data) - 1) {
$o = str_pad(dechex($a), 8, '0', STR_PAD_LEFT) . ' ';
$a += $linesize;
$h = $o . str_pad($h, 50, ' ', STR_PAD_RIGHT) . '|' . $c . '|';
$output .= $h . '<br>';
$c = '';
$h = '';
}
}
}
elseif ($mode == 'b') {
$linesize = 6;
for ($i = 0; $i < strlen($data); $i++) {
$x = substr($data, $i, 1);
$h .= str_pad(decbin(ord($x)), 8, '0', STR_PAD_LEFT) . ' ';
if (ord($x) >= 32 && ord($x) <= 126) {
$c .= $x;
}
else {
$c .= '.';
}
if ($i % $linesize == 5 || $i == strlen($data) - 1) {
$o = str_pad(dechex($a), 8, '0', STR_PAD_LEFT) . ' ';
$a += $linesize;
$h = $o . str_pad($h, 54, ' ', STR_PAD_RIGHT) . '|' . $c . '|';
$output .= $h . '<br>';
$c = '';
$h = '';
}
}
}
// final byte count
$output .=str_pad(dechex(strlen($data)), 8, '0', STR_PAD_LEFT) . ' ';
$output .= '</pre>';
return $output;
}
$x = dump("file1.txt", "h");
echo '<p>Hexadecimal dump of file' . $x . '</p>';
$x = dump("file1.txt", "h", 10, 20);
echo '<p>Hexadecimal dump of 20 bytes of file from offset 10' . $x . '</p>';
$x = dump("file1.txt", "b");
echo '<p>Binary dump of file1' . $x . '</p>';
?>
</syntaxhighlight>
{{out}}
Hexadecimal dump of file
<pre>
00000000 ff fe 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6f 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
00000020 20 00 61 00 20 00 70 00 72 00 6f 00 67 00 72 00 | .a. .p.r.o.g.r.|
00000030 61 00 6d 00 6d 00 69 00 6e 00 67 00 20 00 63 00 |a.m.m.i.n.g. .c.|
00000040 68 00 72 00 65 00 73 00 74 00 6f 00 6d 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3d d8 00 de 2e 00 | .=.....|
00000068
</pre>
Hexadecimal dump of file from offset 10 for length of 20
<pre>
0000000a 74 00 74 00 61 00 20 00 43 00 6f 00 64 00 65 00 |t.t.a. .C.o.d.e.|
0000001a 20 00 69 00 | .i.|
00000014
</pre>
Binary dump of file
<pre>
00000000 11111111 11111110 01010010 00000000 01101111 00000000 |..R.o.|
00000006 01110011 00000000 01100101 00000000 01110100 00000000 |s.e.t.|
0000000c 01110100 00000000 01100001 00000000 00100000 00000000 |t.a. .|
00000012 01000011 00000000 01101111 00000000 01100100 00000000 |C.o.d.|
00000018 01100101 00000000 00100000 00000000 01101001 00000000 |e. .i.|
0000001e 01110011 00000000 00100000 00000000 01100001 00000000 |s. .a.|
00000024 00100000 00000000 01110000 00000000 01110010 00000000 | .p.r.|
0000002a 01101111 00000000 01100111 00000000 01110010 00000000 |o.g.r.|
00000030 01100001 00000000 01101101 00000000 01101101 00000000 |a.m.m.|
00000036 01101001 00000000 01101110 00000000 01100111 00000000 |i.n.g.|
0000003c 00100000 00000000 01100011 00000000 01101000 00000000 | .c.h.|
00000042 01110010 00000000 01100101 00000000 01110011 00000000 |r.e.s.|
00000048 01110100 00000000 01101111 00000000 01101101 00000000 |t.o.m.|
0000004e 01100001 00000000 01110100 00000000 01101000 00000000 |a.t.h.|
00000054 01111001 00000000 00100000 00000000 01110011 00000000 |y. .s.|
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..|
00000068
</pre>
Line 873 ⟶ 1,510:
00000068
</pre>
=={{header|Raku}}==
The hexdump() routine expects a Blob. How you feed it the Blob is up to you. You may read a file in binary mode, encode a string, whatever. Using encoded strings here for a compact, self-contained example. Encoded in a few different ways for variety.
<syntaxhighlight lang="raku" line>say my $string = 'Rosettacode is a programming crestomathy site 😀. 🍨 👨👩👦 ⚽ ¯\_(ツ)_/¯';
say "\nHex dump UTF-16BE, offset 0";
hexdump $string.encode("UTF-16BE");
say "\nHex dump UTF-16LE, offset 0";
hexdump $string.encode("UTF-16LE");
say "\nBinary dump UTF-8, offset 17";
hexdump $string.encode("UTF-8"), :bin, :17offset;
sub hexdump(Blob $blob, Int :$offset is copy = 0, :$bin = False) {
my ($fmt, $space, $batch) = $bin ?? ("%08b", ' ' x 8, 6) !! ("%02X", ' ', 16);
for $blob.skip($offset).batch($batch) {
my @h = flat $_».fmt($fmt), $space xx $batch;
@h[7] ~= ' ';
printf "%08X %s |%s|\n", $offset, @h[^$batch].Str,
$_».chr.join.subst(/<-print>|\t|\n/, '.', :g);
$offset += $batch;
}
}</syntaxhighlight>
{{out}}
<pre>Rosettacode is a programming crestomathy site 😀. 🍨 👨👩👦 ⚽ ¯\_(ツ)_/¯
Hex dump UTF-16BE, offset 0
00000000 00 52 00 6F 00 73 00 65 00 74 00 74 00 61 00 63 |.R.o.s.e.t.t.a.c|
00000010 00 6F 00 64 00 65 00 20 00 69 00 73 00 20 00 61 |.o.d.e. .i.s. .a|
00000020 00 20 00 70 00 72 00 6F 00 67 00 72 00 61 00 6D |. .p.r.o.g.r.a.m|
00000030 00 6D 00 69 00 6E 00 67 00 20 00 63 00 72 00 65 |.m.i.n.g. .c.r.e|
00000040 00 73 00 74 00 6F 00 6D 00 61 00 74 00 68 00 79 |.s.t.o.m.a.t.h.y|
00000050 00 20 00 73 00 69 00 74 00 65 00 20 D8 3D DE 00 |. .s.i.t.e. Ø=Þ.|
00000060 00 2E 00 20 00 20 00 20 00 20 D8 3C DF 68 00 20 |... . . . Ø<ßh. |
00000070 D8 3D DC 68 20 0D D8 3D DC 69 20 0D D8 3D DC 66 |Ø=Üh .Ø=Üi .Ø=Üf|
00000080 00 20 26 BD 00 20 00 AF 00 5C 00 5F 00 28 30 C4 |. &½. .¯.\._.(0Ä|
00000090 00 29 00 5F 00 2F 00 AF |.)._./.¯|
Hex dump UTF-16LE, offset 0
00000000 52 00 6F 00 73 00 65 00 74 00 74 00 61 00 63 00 |R.o.s.e.t.t.a.c.|
00000010 6F 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000020 20 00 70 00 72 00 6F 00 67 00 72 00 61 00 6D 00 | .p.r.o.g.r.a.m.|
00000030 6D 00 69 00 6E 00 67 00 20 00 63 00 72 00 65 00 |m.i.n.g. .c.r.e.|
00000040 73 00 74 00 6F 00 6D 00 61 00 74 00 68 00 79 00 |s.t.o.m.a.t.h.y.|
00000050 20 00 73 00 69 00 74 00 65 00 20 00 3D D8 00 DE | .s.i.t.e. .=Ø.Þ|
00000060 2E 00 20 00 20 00 20 00 20 00 3C D8 68 DF 20 00 |.. . . . .<Øhß .|
00000070 3D D8 68 DC 0D 20 3D D8 69 DC 0D 20 3D D8 66 DC |=ØhÜ. =ØiÜ. =ØfÜ|
00000080 20 00 BD 26 20 00 AF 00 5C 00 5F 00 28 00 C4 30 | .½& .¯.\._.(.Ä0|
00000090 29 00 5F 00 2F 00 AF 00 |)._./.¯.|
Binary dump UTF-8, offset 17
00000011 01110000 01110010 01101111 01100111 01110010 01100001 |progra|
00000017 01101101 01101101 01101001 01101110 01100111 00100000 |mming |
0000001D 01100011 01110010 01100101 01110011 01110100 01101111 |cresto|
00000023 01101101 01100001 01110100 01101000 01111001 00100000 |mathy |
00000029 01110011 01101001 01110100 01100101 00100000 11110000 |site ð|
0000002F 10011111 10011000 10000000 00101110 00100000 00100000 |.... |
00000035 00100000 00100000 11110000 10011111 10001101 10101000 | ð..¨|
0000003B 00100000 11110000 10011111 10010001 10101000 11100010 | ð..¨â|
00000041 10000000 10001101 11110000 10011111 10010001 10101001 |..ð..©|
00000047 11100010 10000000 10001101 11110000 10011111 10010001 |â..ð..|
0000004D 10100110 00100000 11100010 10011010 10111101 00100000 |¦ â.½ |
00000053 11000010 10101111 01011100 01011111 00101000 11100011 |¯\_(ã|
00000059 10000011 10000100 00101001 01011111 00101111 11000010 |..)_/Â|
0000005F 10101111 |¯|</pre>
=={{header|Wren}}==
Line 880 ⟶ 1,584:
As my text editor always adds a trailing \n, the method removes this before dumping the remainder.
<syntaxhighlight lang="
import "./seq" for Lst
import "./fmt" for Fmt
Line 928 ⟶ 1,632:
}
}
var text = "|" + ascii.join(
var offset = start + i * rl
if (i < rc-1 || lc == rl) {
Line 967 ⟶ 1,671:
00000040 68 00 72 00 65 00 73 00 74 00 6f 00 6d 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3d d8 00 de 2e 00 | .=.....
00000068
Line 981 ⟶ 1,685:
00000050 116 000 104 000 121 000 032 000 115 000 |t.h.y. .s.|
0000005a 105 000 116 000 101 000 032 000 061 216 |i.t.e. .=.|
00000064 000 222 046 000 |....
00000068
Line 995 ⟶ 1,699:
00000050 164 000 150 000 171 000 040 000 163 000 |t.h.y. .s.|
0000005a 151 000 164 000 145 000 040 000 075 330 |i.t.e. .=.|
00000064 000 336 056 000 |....
00000068
Line 1,032 ⟶ 1,736:
0000005a 01101001 00000000 01110100 00000000 01100101 00000000 |i.t.e.|
00000060 00100000 00000000 00111101 11011000 00000000 11011110 | .=...|
00000066 00101110 00000000 |..
00000068
Dump of "example_utf16.txt" in base 16 from byte index 2 to 25:
00000002 52 00 6f 00 73 00 65 00 74 00 74 00 61 00 20 00 |R.o.s.e.t.t.a. .|
00000012 43 00 6f 00 64 00 65 00 |C.o.d.e.
0000001a
</pre>
=={{header|XPL0}}==
Works for both MS-DOS and RPi Linux.
<syntaxhighlight lang "XPL0">int Offset, Length, Limit, Byte;
char FileName(80);
func GetByte; \Return a byte from input file
int Return;
[Return:= Byte;
Byte:= ChIn(3); \one-byte look-ahead detects EOF
return Return;
];
proc DumpHex(I); \Show line of hex and its ASCII, starting at offset I
int I, J;
char Line(16);
[HexOut(0, I); Text(0, " ");
SetHexDigits(2);
for J:= 0 to 15 do
[Line(J):= GetByte;
if GetErr and I+J < Limit then Limit:= I+J;
if I+J < Limit then
HexOut(0, Line(J))
else Text(0, " ");
ChOut(0, ^ );
if (J&7) = 7 then ChOut(0, ^ );
];
SetHexDigits(8); \restore default number of digits
ChOut(0, ^|); \display corresponding ASCII characters
for J:= 0 to 15 do
if I+J < Limit then
ChOut(0, if Line(J)<=$1F or Line(J)>=$7F then ^. else Line(J));
ChOut(0, ^|); CrLf(0);
];
func OpenInFile; \Open file for input; return 'true' if success
int FD; \file descriptor
[FD:= FOpen(FileName, 0);
FSet(FD, ^i); \associate device 3 with file; use small buffer (i)
OpenI(3);
return GetErr = 0;
];
func GetFileName; \Get FileName from command line, and set any switches
int C, I; \returns 'true' if no errors
[FileName(0):= 0;
C:= ChIn(8);
loop [while C = $20 do C:= ChIn(8); \skip leading spaces (for MS-DOS)
if C = ^- then
[case ChIn(8) of
^s: Offset:= IntIn(8);
^n: Length:= IntIn(8)
other return false; \Error
Backup; \in case number was terminated by CR or EOF
C:= ChIn(8);
]
else if C = $0D\CR\ or C = $1A\EOF\ then quit
else [I:= 0;
repeat FileName(I):= C;
I:= I+1;
C:= ChIn(8);
until C <= $20;
FileName(I):= 0; \terminate string
];
];
return true;
];
int I;
[Trap(false); \don't abort program on errors
Offset:= 0; Length:= -1>>1;
if not GetFileName then
[Text(0, "Unrecognized switch. Use -s offset, -n length"); exit];
if not OpenInFile(FileName) then
[Text(0, "File not found"); exit];
Byte:= ChIn(3); \look ahead
Limit:= Offset + Length;
if Limit < 0 then Limit:= -1>>1;
for I:= 0 to Offset-1 do \skip any offset bytes
[GetByte; if GetErr then exit];
repeat DumpHex(I);
I:= I + 16;
until I >= Limit;
HexOut(0, Limit); CrLf(0);
]</syntaxhighlight>
{{out}}
<pre>
hexdump examp16.txt
00000000 FF FE 52 00 6F 00 73 00 65 00 74 00 74 00 61 00 |..R.o.s.e.t.t.a.|
00000010 20 00 43 00 6F 00 64 00 65 00 20 00 69 00 73 00 | .C.o.d.e. .i.s.|
00000020 20 00 61 00 20 00 70 00 72 00 6F 00 67 00 72 00 | .a. .p.r.o.g.r.|
00000030 61 00 6D 00 6D 00 69 00 6E 00 67 00 20 00 63 00 |a.m.m.i.n.g. .c.|
00000040 68 00 72 00 65 00 73 00 74 00 6F 00 6D 00 61 00 |h.r.e.s.t.o.m.a.|
00000050 74 00 68 00 79 00 20 00 73 00 69 00 74 00 65 00 |t.h.y. .s.i.t.e.|
00000060 20 00 3D D8 00 DE 2E 00 | .=.....|
00000068
hexdump -s 20 examp16.txt -n 20
00000014 6F 00 64 00 65 00 20 00 69 00 73 00 20 00 61 00 |o.d.e. .i.s. .a.|
00000024 20 00 70 00 | .p.|
00000028
</pre>
|