简体   繁体   中英

What is the equivalent of Matlab's default display function which outputs to a file instead of stdout?

I apologize if this question is badly named, but let me explain through a simple analogy to Java. Please note, this question is about Matlab, not Java.

In Java, the standard way to write to the stdout stream is to say System.out.println . If we want to print this exact output to a file, we can create a PrintStream object myPrinter , point it at a file, and replace the call to System.out.println with the call to myPrinter.println .

System.out.println("Hello World");
PrintStream myPrinter = new PrintStream(new File("MyJournal.log"));
myPrinter.println("Hello Log");

In Matlab, one standard way to write to standard out is to write an expression, variable or statement without a following semicolon. How would I rewrite my Matlab statements to get this (ascii) output into a file instead?

I would like to avoid solutions that redirect stdout to a file, because I still want some things printed to the console.

Additionally, I do not want to have to specify the type of the object that is being written to file, because the standard way does not require type specification.

Update: In particular, as far as I know, the printf family of functions requires type specification (different format string depending on the type of object). I am trying to avoid this because I seek a more generic solution.

What you want to do is find a generic string conversion that looks like display() , use that to build your output as strings, and then you can pass it to fprintf() or other normal output functions.

The Matlab output produced by omitting the semicolon is done by calling display() on the result of the expression. Matlab provides a display implementation for all the builtin types and a fallback implementation for user-supplied objects. The disp() function displays the value in the same way, but omits the variable name.

This is basically the equivalent of Java's toString function which is getting called behind the scenes when you print arbitrary objects to a PrintStream . The display functionality is mostly not in PrintStream itself, but in the polymorphic toString method that knows how to convert objects to display strings. The difference is that Java toString returns a String data value, which is easy to work with programmatically and compose with other operations, so you can manipulate it send it where you want, but Matlab's display and disp always output to stdout instead of giving you a string back.

What you want is probably something that will give you display -style output as a string, and then you can output it where you want, using fprintf() or another string output function.

One easy approach is to use evalc() to just call display and capture the output. The evalc function lets you run arbitrary Matlab code, and capture the output that would have gone to stdout to a char variable instead. You can make a generic conversion function and apply it to any values you want.

function out = tostr(x)
    out = evalc('disp(x)');
end

The other option is to define a new dispstr() function, write it to convert Matlab built-in types (maybe using the evalc technique), and override dispstr in the objects you write, and call it polymorphically. More work, but it could end up being cleaner and faster, because evalc is slow and sometimes fragile. Also have a look at mat2str for ideas on an alternate output mechanism.

Then you'd be able to output values generically, without specifying the type, with calls like this. Note that in the second form, the placeholders are all just %s regardless of the type of object.

function displaySomeArbitraryDataValues(fh, foo, bar, baz)
% fh is a file handle previously opened with fopen()
fprintf(fh, 'foo=%s, bar=%s and baz=%s', tostr(foo), tostr(baz), tostr(qux))
end

Matlab does not have an formatted output function that automatically calls a display conversion, so you'll have to call the conversions explicitly in a lot of cases, so it'll be a little more wordy than Java. (Unless you want to go all out and write your own polymorphic auto-converting output functions or string wrapper objects.) If you want to use placeholders, it's easy enough by forcing all the args to be converted.

function out = sprintf2(format, varargin)
%SPRINTF2 A sprintf equivalent with polymorphic input conversion
% Use '%s' placeholders for everything in format, regardless of arg type
args = varargin;
strs = {}
for i = 1:numel(args)
    strs{i} = tostr(args{i});
end
out = sprintf(format, strs{:});
end

If you want to get fancy, you could do mixed printf conversions by parsing the printf format argument yourself, defining a new placeholder like %y that calls your tostr() on the argument and then prints that string (probably by replacing the placeholder with %s and the argument with the tostr() result), and passes all the normal placeholders along to printf with un-converted arguments. This is kind of difficult to implement and can be computationally expensive, though.

You could make it behave more like Java by providing char conversions that convert object values to display strings, but that's inconsistent with how Matlab's existing numeric to char conversions work, so it wouldn't be fully generic, and you would run in to some odd edge cases, so I wouldn't recommend that. You could do a safer form of this by defining a new @string class that wraps char strings, but does implicit conversions by calling your tostr() instead of char() . This could be a big performance hit, though, because Matlab OOP objects are substantially slower than operations with built-in types and plain functions.

For background: basically, the reason you need to pass explicit conversions to fprintf in Matlab, but you don't need to with the PrintStream stuff in Java is that fprintf is inherited from C, which did not have run time type detection, especially of varargs, in the language. Matlab does, so fprintf is more limited than it needs to be. However, what fprintf does give you is fine-grained control over the formatting of numeric values and a concise calling form. These are useful, as evidenced by how Java programmers complained for years about not having them in Java and eventually got them added. It's just that Matlab sticks to the C-supported fprintf conversions, where they could easily add a couple new generic conversions that examine the type of the input at runtime and give you the generic output support you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM