什么是Matlab的默认显示功能,它输出到文件而不是stdout?

时间:2013-04-28 19:44:21

标签: matlab io

如果这个问题命名错误,我道歉,但让我通过一个简单的类比来解释Java。 请注意,这个问题是关于Matlab而不是Java。

在Java中,写入stdout流的标准方法是System.out.println。 如果我们想要将这个确切的输出打印到文件,我们可以创建一个PrintStream对象myPrinter,将其指向一个文件,并将调用替换为System.out.println,调用{{ 1}}。

myPrinter.println

在Matlab中,写入标准输出的一种标准方法是编写表达式,变量或语句而不使用后面的分号。 如何重写我的Matlab语句以将此(ascii)输出转换为文件?

我想避免将System.out.println("Hello World"); PrintStream myPrinter = new PrintStream(new File("MyJournal.log")); myPrinter.println("Hello Log"); 重定向到文件的解决方案,因为我仍然希望在控制台上打印一些内容。

此外,我不想指定要写入文件的对象的类型,因为标准方式不需要类型规范。

更新:特别是,据我所知,stdout系列函数需要类型规范(不同的格式字符串,具体取决于对象的类型)。我试图避免这种情况,因为我寻求更通用的解决方案。

1 个答案:

答案 0 :(得分:6)

您要做的是找到一个类似于display()的通用字符串转换,使用它来将输出构建为字符串,然后您可以将其传递给fprintf()或其他正常输出函数。

通过省略分号产生的Matlab输出是通过对表达式的结果调用display()来完成的。 Matlab为所有内置类型提供了display实现,并为用户提供的对象提供了回退实现。 disp()函数以相同的方式显示值,但省略变量名。

这基本上相当于Java的toString函数,当您将任意对象打印到PrintStream时,它会在幕后调用。显示功能大部分不在PrintStream本身,而是在多态toString方法中,该方法知道如何将对象转换为显示字符串。不同之处在于Java toString返回一个String数据值,它易于以编程方式工作并与其他操作组合,因此您可以操纵它将其发送到您想要的位置,但Matlab的display和{{ 1}}总是输出到stdout而不是给你一个字符串。

你想要的东西可能会给你disp - 样式输出作为字符串,然后你可以使用display或其他字符串输出函数将它输出到你想要的地方。

一种简单的方法是使用fprintf()来调用evalc()并捕获输出。 display函数允许您运行任意Matlab代码,并将已转移到evalc的输出捕获到stdout变量。您可以创建通用转换函数并将其应用于您想要的任何值。

char

另一种选择是定义一个新的function out = tostr(x) out = evalc('disp(x)'); end 函数,编写它来转换Matlab内置类型(可能使用dispstr()技术),并覆盖对象中的evalc写,并以多态方式调用它。更多的工作,但它可能最终更清洁,更快,因为dispstr是缓慢的,有时是脆弱的。另请查看evalc关于备用输出机制的想法。

然后,您可以通过这样的调用一般性地输出值,而无需指定类型。请注意,在第二种形式中,无论对象的类型如何,占位符都只是mat2str

%s

Matlab没有自动调用显示转换的格式化输出函数,所以你必须在很多情况下明确地调用转换,所以它会比Java更加冗长。 (除非你想全力以赴并编写自己的多态自动转换输出函数或字符串包装器对象。)如果你想使用占位符,通过强制转换所有的args很容易。

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

如果您想获得幻想,可以通过自己解析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 格式参数来进行混合printf次转换,定义一个新的占位符,例如调用printf的{​​{1}}在参数上然后打印该字符串(可能通过用%y替换占位符和带有tostr()结果的参数),并将所有正常占位符传递给%s未转换参数。但这很难实现,但计算成本很高。

可以通过提供将对象值转换为显示字符串的tostr()次转换来使其行为更像Java,但这与Matlab现有数据到printf转换的工作方式不一致,所以它不是完全通用的,你会遇到一些奇怪的边缘情况,所以我不建议这样做。您可以通过定义包含char字符串的新char类来执行更安全的表单,但可以通过调用@string而不是char进行隐式转换。但这可能是一个很大的性能影响,因为Matlab OOP对象比使用内置类型和普通函数的操作慢得多。

对于背景:基本上,您需要在Matlab中将显式转换传递给tostr(),但是您不需要使用Java中的char()内容fprintf是继承自C,在语言中没有运行时类型检测,特别是varargs。 Matlab确实如此,因此PrintStream比它需要的更有限。但是,fprintf给你的是对数值格式和简洁调用形式的细粒度控制。这些都是有用的,正如Java程序员多年来一直抱怨他们没有使用Java并最终添加它们一样。只是Matlab坚持使用C支持的fprintf转换,他们可以轻松添加一些新的通用转换,在运行时检查输入的类型,并为您提供所需的通用输出支持。