15
\$\begingroup\$

Challenge

Create a console program to display each byte of a file.


Winning

Since this is , fewest bytes wins.


Rules

  • Program must be a console application, meaning that it will be ran from some sort of command-line interpreter;
  • Every byte must be uppercase hexadecimal, separated by a space, and it must be 2 digits; (put number 0 before it if it has 1 digit)
  • File must be read using IO or alternative, and not hard-coded;
  • File path must be specified as a command-line argument or a user prompt (like STDIN);
  • No loopholes please;

Example

test.txt (ends with LF)

Hello World!

$ ./hexdump.exe test.txt
48 65 6C 6C 6F 20 57 6F 72 6C 64 21 0A
\$\endgroup\$
13
  • 16
    \$\begingroup\$ @facepalm42 To avoid facepalms, I strongly recommend using the Sandbox to help you design future challenges before posting them. \$\endgroup\$
    – Adám
    Commented Jul 9, 2019 at 10:13
  • 2
    \$\begingroup\$ How is it possible to display all byte values at once, if it won't fit on the screen? Scrolling clearly isn't "at once". Also, what's wrong with (a function) just returning the values? \$\endgroup\$
    – Adám
    Commented Jul 9, 2019 at 10:16
  • 7
    \$\begingroup\$ @facepalm42 Please don't change the spec so long time after posting the challenge. The original post didn't specify the exact format of the hexadecimal numbers, leaving it up to the answerers. Your latest edit invalidated my existing answer! \$\endgroup\$
    – Adám
    Commented Jul 9, 2019 at 10:31
  • 11
    \$\begingroup\$ Is there a particular reason you only allow command-line argument or a user prompt? What's wrong with e.g. taking the file name as a function argument? \$\endgroup\$
    – Adám
    Commented Jul 9, 2019 at 10:40
  • 3
    \$\begingroup\$ It would be helpful if you had a simple hello.txt text file as an example as an input and what the expected output should be. For instance, if the hello.txt contained simply the word hello with a line break, how would this be expressed in the output? Are you grouping the bytes in 16-bit,32-bit or 64-bit words? Or is each byte expressed as two-digit hex? Are spaces acceptable after each byte as hex, or after each x-bit word? Do you require an 0x pre-fix for each byte? \$\endgroup\$ Commented Jul 9, 2019 at 10:49

29 Answers 29

11
\$\begingroup\$

C (gcc) on *nix, 73 71 bytes

i;main(c,v)int**v;{for(c=open(v[1],0);read(c,&i,1);printf("%02X ",i));}

Try it online! Test suite

-2 bytes thanks to Johan du Toit

This relies on O_RDONLY == 0 and on int_one == 1 where int int_one; *(char*)&int_one = 1;.

\$\endgroup\$
0
7
\$\begingroup\$

PowerShell, 45 40 bytes

"$(gc $args -ra|% *ay|%{'{0:X2}'-f+$_})"

Try it online!

-5 bytes thanks to mazzy

\$\endgroup\$
2
  • \$\begingroup\$ thanks for ./.input.tio. 40 bytes with CRLF preserved. \$\endgroup\$
    – mazzy
    Commented Jul 10, 2019 at 5:29
  • 1
    \$\begingroup\$ I learned this from the Kevin Cruijssen solution. \$\endgroup\$ Commented Jul 10, 2019 at 8:41
7
\$\begingroup\$

PHP, 60 59 54 bytes

<?=wordwrap(bin2hex(implode(file($argv[1]))),2,' ',1);
  • -1 byte thanks to manassehkatz
  • -5 bytes thanks to Blackhole

Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Should be able to drop the trailing ?> and save 2 bytes, or if that doesn't work then replace ?> with a semicolon and save 1 byte. \$\endgroup\$ Commented Jul 10, 2019 at 4:34
  • 3
    \$\begingroup\$ Use implode(file($x)) instead of file_get_contents($x) (-4 bytes). \$\endgroup\$
    – Blackhole
    Commented Jul 10, 2019 at 13:45
  • 3
    \$\begingroup\$ And wordwrap(), with 1 as the last parameter, is one byte shorter than chunk_split(). \$\endgroup\$
    – Blackhole
    Commented Jul 10, 2019 at 13:54
6
\$\begingroup\$

Ruby, 26 bytes

$<.bytes{|b|$><<"%02X "%b}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Does this read the contents of a file given a file-path as program argument? Based on the TIO it seems to just read from STDIN, but I don't know Ruby well-enough to say it's incorrect. \$\endgroup\$ Commented Jul 10, 2019 at 18:33
  • 1
    \$\begingroup\$ @KevinCruijssen Yes, it takes the file path(s) as program argument. If there are no arguments, $< switches to reading from STDIN instead. \$\endgroup\$
    – Value Ink
    Commented Jul 13, 2019 at 1:14
6
\$\begingroup\$

Java 11, 156 154 bytes

import java.nio.file.*;interface M{static void main(String[]a)throws Exception{for(int b:Files.readAllBytes(Path.of(a[0])))System.out.printf("%02X ",b);}}

-2 bytes thanks to @Holger.

Try it online by using ./.input.tio as argument file-path, which will have a given input as file-content.

Explanation:

import java.nio.file.*;        // Required import for Files and Paths
interface M{                   // Class
  static void main(String[]a)  //  Mandatory main method
      throws Exception{        //  With mandatory thrown clause for the readAllBytes builtin
                                         a[0]    // Get the first argument
                                 Path.of(    )   // Get the file using that argument as path
              Files.readAllBytes(             )  // Get all bytes from this file
    for(int b:                                 ) // Loop over each of them:
      System.out.printf(                         //  And print the current byte
                        "%02X ",b);}}            //  As uppercase hexadecimal with leading 0
                                                 //  and trailing space as delimiter
\$\endgroup\$
6
  • \$\begingroup\$ What's the rationale behind using interface instead of class? \$\endgroup\$
    – JakeDot
    Commented Jul 10, 2019 at 10:06
  • 4
    \$\begingroup\$ @JakeDot main is required to be public, interface methods are always public, interface is shorter than class + public. \$\endgroup\$
    – Grimmy
    Commented Jul 10, 2019 at 11:00
  • 3
    \$\begingroup\$ With Java 11, you can use Path.of instead of Paths.get \$\endgroup\$
    – Holger
    Commented Jul 10, 2019 at 12:02
  • 1
    \$\begingroup\$ @Holger Thanks! :) \$\endgroup\$ Commented Jul 10, 2019 at 12:27
  • 2
    \$\begingroup\$ @Grimy since Java 9, interface methods are not always public, but they are public unless explicitly declared private. \$\endgroup\$
    – Holger
    Commented Jul 10, 2019 at 12:30
5
\$\begingroup\$

Perl 5 (-aF//), 23 bytes

printf"%02X ",ord for@F

TIO

\$\endgroup\$
5
\$\begingroup\$

Python 3, 59 bytes

-11 bytes thanks to Mostly Harmless!

-8 bytes thanks to James K Polk!

-24 bytes thanks to Blue!

print(' '.join('%02X'%ord(i)for i in open(input()).read()))

Try it online!

This is pretty straightforward; it opens a filename given as input on STDIN, reads it, converts each character to its ASCII value, converts each number to hex, strips off the "0x" that precedes hexademical values in Python, pads the value with a zero if necessary, then joins the values together with spaces.

\$\endgroup\$
6
  • \$\begingroup\$ Can save a few bytes with '%02X'%ord(i) instead of slicing the output of hex \$\endgroup\$ Commented Jul 9, 2019 at 23:22
  • \$\begingroup\$ @MostlyHarmless Done! -11 bytes. Thanks! \$\endgroup\$ Commented Jul 10, 2019 at 0:37
  • \$\begingroup\$ how about '%02X' instead of '%02x', and get rid of .upper() \$\endgroup\$ Commented Jul 10, 2019 at 0:50
  • \$\begingroup\$ You can save the bytes from the import sys by using raw_input() as the filename instead; rules allow user prompting. \$\endgroup\$
    – Blue
    Commented Jul 10, 2019 at 12:11
  • \$\begingroup\$ @Blue Thanks! And it's even shorter in Python 3, where you can just do input() \$\endgroup\$ Commented Jul 10, 2019 at 15:32
4
\$\begingroup\$

APL (Dyalog Unicode), 16 bytes

Anonymous tacit prefix function. Returns (and implicitly prints, if the value isn't otherwise consumed) a two-row matrix with the top 4 bits represented as a decimal number 0–15 in the top row and the bottom 4 bits similarly represented in the bottom row. That is, the matrix has as many columns as the file has bytes.

16 16⊤83 ¯1∘⎕MAP

Try it online!

⎕MAP map the argument filename to an array
 with parameters:
¯1 the entire length of the file
83 read as 8-bit integers

16 16⊤ convert (anti-base) to 2-position hexadecimal

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @facepalm42 It very much is in hexadecimal. E.g. H is 72, which is 4×16¹+8×16⁰ or [4,8]₁₆. Hence the first column in the example reads [4,8]. \$\endgroup\$
    – Adám
    Commented Jul 9, 2019 at 10:28
  • \$\begingroup\$ Oh, I completely forgot! Sorry. \$\endgroup\$
    – mekb
    Commented Jul 9, 2019 at 10:29
3
\$\begingroup\$

Bash,  33  23 bytes

...with a lot of help:
-3 thanks to manatwork
-4 thanks to spuck
-3 thanks to Nahuel Fouilleul

echo `xxd -c1 -p -u $1`

Try it online!

Note that the TIO link above uses input - we can write files locally, so this shows it working as a program taking a file path.

\$\endgroup\$
8
  • \$\begingroup\$ Minor reductions: xxd -u -p $1|fold -2|tr \\n \ . \$\endgroup\$
    – manatwork
    Commented Jul 9, 2019 at 13:07
  • \$\begingroup\$ Thanks, any idea how to get the \n and \ to work in the 'this' link version? EDIT: I added another escape character. \$\endgroup\$ Commented Jul 9, 2019 at 13:25
  • \$\begingroup\$ If I understand you correctly, you just want to change from double quotes to single quotes: Try it online! \$\endgroup\$
    – manatwork
    Commented Jul 9, 2019 at 13:41
  • \$\begingroup\$ Awesome thank you! \$\endgroup\$ Commented Jul 9, 2019 at 13:51
  • \$\begingroup\$ xxd -c1 -p -u $1|tr \\n \ \$\endgroup\$
    – spuck
    Commented Jul 10, 2019 at 4:35
3
\$\begingroup\$

Kotlin, 130 127 104 93 92 bytes

fun main(a:Array<String>){java.io.File(a[0]).readBytes().forEach{print("%02X ".format(it))}}

Try it online!

Edit: -11 bytes thanks to @ChrisParton

Edit: Working TIO

Edit: -1 byte thanks to @KevinCruijssen

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Could you ditch the import and reference File as java.io.File instead? \$\endgroup\$ Commented Jul 10, 2019 at 5:43
  • \$\begingroup\$ @ChrisParton right you are, thanks! \$\endgroup\$
    – Quinn
    Commented Jul 10, 2019 at 12:59
  • \$\begingroup\$ Here a working TIO. You can use ./.input.tio as file-path argument, and it will use the STDIN as file-content. :) \$\endgroup\$ Commented Jul 10, 2019 at 18:36
  • \$\begingroup\$ @KevinCruijssen thanks! just updated answer \$\endgroup\$
    – Quinn
    Commented Jul 10, 2019 at 18:40
  • 1
    \$\begingroup\$ I don't know Kotlin, but the TIO still works if I remove the space at a:Array, so I think you can save a byte. \$\endgroup\$ Commented Jul 10, 2019 at 19:51
2
\$\begingroup\$

Dart, 140 134 bytes

import'dart:io';main(a){print(new File(a[0]).readAsBytesSync().map((n)=>n.toRadixString(16).toUpperCase().padLeft(2,'0')).join(' '));}

Try it online!

-6 bytes because I forgot to reduce variable names

\$\endgroup\$
2
  • \$\begingroup\$ +1 for dart. Such an underrated language. \$\endgroup\$
    – vasilescur
    Commented Jul 9, 2019 at 14:26
  • \$\begingroup\$ Hard to golf with, since it's basically JS without the very lax type system \$\endgroup\$
    – Elcan
    Commented Jul 9, 2019 at 14:27
2
\$\begingroup\$

Haskell, 145 143 bytes

import System.Environment
import Text.Printf
import Data.ByteString
main=getArgs>>=Data.ByteString.readFile.(!!0)>>=mapM_(printf"%02X ").unpack
\$\endgroup\$
1
  • 1
    \$\begingroup\$ A little bit shorter: import Data.ByteString plus main=getArgs>>=Data.ByteString.readFile.(!!0)>>=mapM_(printf"%02X ").unpack. \$\endgroup\$
    – nimi
    Commented Jul 9, 2019 at 18:07
2
\$\begingroup\$

Rust, 141 bytes (contributed version)

use std::{io::*,fs::*,env::*};fn main(){for x in File::open(args().nth(1).unwrap()).unwrap().bytes(){print!("{:02X} ",x.unwrap())}println!()}

Rust, 151 bytes (original version)

fn main(){std::io::Read::bytes(std::fs::File::open(std::env::args().nth(1).unwrap()).unwrap()).map(|x|print!("{:02X} ",x.unwrap())).count();println!()}
\$\endgroup\$
1
  • \$\begingroup\$ -10 bytes: TIO \$\endgroup\$
    – Endenite
    Commented Jul 10, 2019 at 16:04
2
\$\begingroup\$

bash+Stax, 6+4+1=11 bytes

This is complete theory craft at this point. You can't actually run this. If everything works according to its spec this would work, but not everything does yet.

The bash script is

]<$1

and the stax program must be compiled and saved to ] is

╛↕ßú┼_

Set your character set to ISO 8859-1 (Windows-1252 won't work here) and go

Unpacked and explained

_          push all input as a single array
F          run the rest of the program for each element of the array
 |H        write the hex of the byte to standard output
 |         write a space to standard output
\$\endgroup\$
2
\$\begingroup\$

Emojicode, 186 162 bytes

📦files🏠🏁🍇🔂b🍺📇🐇📄🆕🔡👂🏼❗️❗️🍇👄📫🍪🔪🔡🔢b❗️➕256 16❗️1 2❗️🔤 🔤🍪❗️❗️🍉🍉

Try it online here.

Ungolfed:

📦 files 🏠  💭 Import the files package into the default namespace
🏁 🍇  💭 Main code block
🔂 b  💭 For each b in ...
  🍺  💭 (ignoring IO errors)
  📇 🐇 📄  💭 ... the byte representation of the file ...
  🆕 🔡 👂🏼  💭 ... read from user input:
  ❗️ ❗️ 🍇
    👄  💭 Print ...
    📫  💭 ... in upper case (numbers in bases > 10 are in lower case) ...
    🍪  💭 ... the concatenation of:
      🔪 🔡 🔢 b ❗️ ➕ 256  💭 b + 256 (this gives the leading zero in case the hex representation of b is a single digit) ...
              16  💭 ... represented in hexadecimal ...
           ❗️
         1 2  💭 ... without the leading one,
      ❗️
      🔤 🔤  💭 ... and a space
    🍪
    ❗️❗️
  🍉
🍉
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 45 bytes

@*ARGS[0].IO.slurp(:bin).list.fmt('%02X').say

Try it online!

  • @*ARGS[0] is the first command-line argument.
  • .IO turns that (presumed) filename into an IO::Path object.
  • .slurp(:bin) reads the entire file into a Buf buffer of bytes. (Without the :bin the file contents would be returned as a Unicode string.)
  • .list returns a list of the byte values from the buffer.
  • .fmt('%02X') is a List method that formats the elements of the list using the given format string, then joins them with spaces. (Convenient!)
  • .say prints that string.
\$\endgroup\$
2
  • \$\begingroup\$ Based on the Python answer, a TIO Link is in fact quite possible. \$\endgroup\$ Commented Jul 9, 2019 at 21:35
  • \$\begingroup\$ Some rearranging can remove the .list for 41 bytes \$\endgroup\$
    – Jo King
    Commented Jul 13, 2019 at 4:01
2
\$\begingroup\$

Node.js, 118 bytes

console.log([...require("fs").readFileSync(process.argv[2])].map(y=>(y<16?0:"")+y.toString(16).toUpperCase()).join` `)

What the result looks like: enter image description here

Btw the content of test.txt in the example is as follows:

做乜嘢要輸出大楷姐,搞到要加番toUpperCase()去轉番,咁就13byte啦。

(Why on earth is upper-case output necessary. I had to add the conversion with toUpperCase(), and that cost 13 bytes.)

\$\endgroup\$
1
  • \$\begingroup\$ using ... for an array is actually pretty cool \$\endgroup\$
    – mekb
    Commented May 8, 2021 at 13:47
1
\$\begingroup\$

D, 98 Bytes

import std;void main(string[]s){File(s[1]).byChunk(9).joiner.each!(a=>writef("%02X ",a.to!byte));}

Try it Online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 75 bytes

Mostly a copy of Maxwell's python 2 answer.

import sys
print(' '.join('%02X'%b for b in open(sys.argv[1],'rb').read()))
\$\endgroup\$
2
  • \$\begingroup\$ you mean probably sys.argv[1]. with sys.argv[0] this script works more like a quine ;-) \$\endgroup\$
    – anion
    Commented Jul 10, 2019 at 13:22
  • \$\begingroup\$ @anion: oops, haha, fixing ... \$\endgroup\$ Commented Jul 10, 2019 at 13:32
1
\$\begingroup\$

Racket, 144 bytes

This submission does output a trailing space, and no trailing newline. Let me know if this is considered a loophole :)

(command-line #:args(f)(for([b(call-with-input-file f port->bytes)])(printf"~a "(string-upcase(~r b #:base 16 #:min-width 2 #:pad-string"0")))))

Cleaned up

(command-line #:args (f)
 (for ([b (call-with-input-file f port->bytes)])
   (printf "~a "
           (string-upcase
            (~r b #:base 16 #:min-width 2 #:pad-string "0")))))
\$\endgroup\$
1
\$\begingroup\$

Forth (gforth), 71 bytes

: f slurp-file hex 0 do dup c@ 0 <# # # #> type space 1+ loop ;
1 arg f

Try it online!

TIO has 3 arg in the last line because TIO passes "-e bye" to the command line parser before passing in the code

Code Explanation

: f             \ start a function definition
  slurp-file    \ open the file indicated by the string on top of the stack,
                \ then put its contents  in a new string on top of the stack
  hex           \ set the interpreter to base 16
  0 do          \ loop from 0 to file-length - 1 (inclusive)
    dup c@      \ get the character value from the address on top of the stack
    0 <# # # #> \ convert to a double-length number then convert to a string of length 2
    type        \ output the created string 
    space       \ output a space 
    1+          \ add 1 to the current address value
  loop          \ end the loop
;               \ end the word definition
1 arg f         \ get the filename from the first command-line argument and call the function
\$\endgroup\$
1
\$\begingroup\$

Javascript, 155 bytes

for(b=WScript,a=new ActiveXObject("Scripting.FileSystemObject").OpenTextFile(b.Arguments(0));;b.echo(('0'+a.read(1).charCodeAt(0).toString(16)).slice(-2)))
\$\endgroup\$
1
\$\begingroup\$

VBScript, 143 bytes

set a=CreateObject("Scripting.FileSystemObject").OpenTextFile(WScript.Arguments(0)):while 1 WScript.echo(right("0"+Hex(Asc(a.read(1))),2)):wend
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 94 89 bytes

Print@ToUpperCase@StringRiffle@IntegerString[BinaryReadList@Last@$ScriptCommandLine,16,2]

Try it online!

The code is quite self-explanatory because of the long command names. It should be read mostly from right to left:

$ScriptCommandLine       is a list of {scriptname, commandlinearg1, commandlinearg2, ...}
Last@...                 extracts the last command-line argument
BinaryReadList@...       reads the named file into a list of bytes
IntegerString[...,16,2]  converts each byte to a 2-digit hex string (lowercase)
StringRiffle@...         converts this list of strings into a single string with spaces
ToUpperCase@...          converts the string to uppercase
Print@...                prints the result to stdout
\$\endgroup\$
1
\$\begingroup\$

Gema, 45 characters

?=@fill-right{00;@radix{10;16;@char-int{?}}} 

Sample run:

bash-5.0$ gema '?=@fill-right{00;@radix{10;16;@char-int{?}}} ' <<< 'Hello World!'
48 65 6C 6C 6F 20 57 6F 72 6C 64 21 0A 

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pyth, 12 bytes

jdcr1.Hjb'w2

Try it online!

Takes input as user prompt (no way to access command-line arguments AFAIK).

jd           # join on spaces
  c        2 # chop into pieces of length 2
   r1        # convert to uppercase
     .H      # convert to hex string, interpreting as base 256 (*)
       jb    # join on newlines
         '   # read file as list of lines
          w  # input()

(*) I'm not 100% sure if this is intended, but one base 256 digit (as in, one character), will always convert into exactly 2 hex digits, eliminating the need to pad with zeroes.

\$\endgroup\$
0
\$\begingroup\$

C# .NET Framework 4.7.2 - 235 213 203 191 175 140 bytes

Try it online!

using System.IO;class P{static void Main(string[]a){foreach(var b in File.ReadAllBytes(a[0])){System.Console.Write(b.ToString("X2")+" ");}}}

using System;
using System.IO;

namespace hexdump
{
    class Program
    {
        static void Main(string[] args)
        {
            // Read the bytes of the file
            byte[] bytes = File.ReadAllBytes(args[0]);

            // Loop through all the bytes and show them
            foreach (byte b in bytes)
            {
                // Show the byte converted to hexadecimal
                Console.Write(b.ToString("X2") + " ");
            }
        }
    }
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think the following will save some bytes (now 181 I think): using System.IO;class P{static void Main(string[] a){if(a.Length>0 && File.Exists(a[0])){foreach(var b in File.ReadAllBytes(a[0])){System.Console.Write($"{b.ToString("X2")} ");}}}} \$\endgroup\$
    – PmanAce
    Commented Jul 17, 2019 at 15:05
  • \$\begingroup\$ @PmanAce If you remove some of the whitespace, it gets down to 175. \$\endgroup\$
    – mekb
    Commented Jul 18, 2019 at 5:58
0
\$\begingroup\$

05AB1E, 18 bytes

IvyÇh2j' 0.:' Jvy?

Try it online!

Explanation:

IvyÇh2j' 0.:' Jvy?
Iv                 Loop through each character in input
  y                Push current character
   Ç               ASCII value
    h              Convert to hexadecimal
     2j            Pad with at least 2 spaces
       ' 0.:       Replace all spaces with 0s
            ' J    Add space to end
               vy? Convert to string and print
IvyÇh2j' 0.:' Jvy?
\$\endgroup\$
0
\$\begingroup\$

Free Pascal, 81 B

var c:char;begin while not EOF do begin read(c);write(hexStr(ord(c),2):3)end end.

Note, output has a leading blank and no trailing newline:
48 65 6C 6C 6F 20 57 6F 72 6C 64 21 0A


−3 B: By default the FPC (FreePascal Compiler) has the “FPC compiler compatibility mode” selected. When compiling in FPC’s “ISO standard compiler compatibility mode” the file buffer variables (here specifically input^) and “low-level” I/O routines like get become available. The following code needs to be compiled with fpc ‑MISO sourceCode.pas:

begin while not EOF do begin write(hexStr(ord(input^),2):3);get(input)end end.

−10 B: Furthermore, if input was guaranteed to be non-empty, we can use a repeat … until … loop instead of the bulky while … do begin … end:

begin repeat write(hexStr(ord(input^),2):3);get(input)until EOF end.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.