I'm trying to build a Flutter App and learning Dart in the process, but I'm getting kind of frustrated when debugging. I have fetched a resource from an API and now I want to print the JSON string to the console, but it keeps cutting off the string.
So I actually have two questions: is the terminal console really the only way to print debug messages and how can I print large strings to the console without them automatically getting cut off?
How about using the Flutter log from the dart: developer library. This does not seem to have the maximum length limit like print() or debugPrint(). This is the only solution that seems to work fine. Try it as below:
import 'dart:developer';
log(reallyReallyLongText);
The output will be the entire long string without breaks and prefixed with [log]
You can make your own print. Define this method
void printWrapped(String text) {
final pattern = RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}
Use it like
printWrapped("Your very long string ...");
Credit
Use debugPrint with the optional parameter to wrap according to the platform's output limit.
debugPrint(someSuperLongString, wrapWidth: 1024);
Currently dart doesn't support printing logs more than 1020 characters (found that out by trying).
So, I came up with this method to print long logs:
static void LogPrint(Object object) async {
int defaultPrintLength = 1020;
if (object == null || object.toString().length <= defaultPrintLength) {
print(object);
} else {
String log = object.toString();
int start = 0;
int endIndex = defaultPrintLength;
int logLength = log.length;
int tmpLogLength = log.length;
while (endIndex < logLength) {
print(log.substring(start, endIndex));
endIndex += defaultPrintLength;
start += defaultPrintLength;
tmpLogLength -= defaultPrintLength;
}
if (tmpLogLength > 0) {
print(log.substring(start, logLength));
}
}
}
There is an open issue for that: https://github.com/flutter/flutter/issues/22665
debugPrint and print are actually truncating the output.
You can achieve this using the Logger Plugin: https://pub.dev/packages/logger
To print any type of log Just do the do the following.
var logger = Logger();
logger.d("Logger is working!");// It also accept json objects
In fact, it will even format the output for you.
Please try debugPrint('your output'); instead of print('your output'); the documentation is here if you would like to read. debugPrint throttles the output to a level to avoid being dropped by android's kernel as per the documentation.
Here is a one-liner based on #CopsOnRoad's answer that you can quickly copy and paste (such as: when you want to slightly modify your code and log some data and see temporarily):
void printWrapped(String text) => RegExp('.{1,800}').allMatches(text).map((m) => m.group(0)).forEach(print);
Method 1
void prints(var s1) {
String s = s1.toString();
debugPrint(" =======> " + s, wrapWidth: 1024);
}
Method 2
void prints(var s1) {
String s = s1.toString();
final pattern = RegExp('.{1,800}');
pattern.allMatches(s).forEach((match) => print(match.group(0)));
}
Just call this method to print your longggg string
If you run the application in android studio it will truncate long string.
In xcode 10.2 which i am using long string is not truncating.
My suggestion is write print statement logs and run the application in Xcode instead of android studio.
Same issue caused lot of frustration when I have to test base64 of images.
I was using iTerm2 editor, so the answer is specific to the iTerm2
1. Navigate to Preferences -> Profiles
2. Select your Profile (in my case was **Default** only)
3. Select **Terminal** in the header of right pan
4. Check Unlimited scrollback
Now you can have copy the large strings from the terminal.
Related
I'm trying to write some code for the the ESP8266-12E that detects initial program load of a new version of the code. For this simplified version of my code (that still exhibits the behavior I'm seeing) there is no code in the loop() section.
I place my current version of the code in a const String pgmVersion. The code reads the EEPROM (actually flash for the ESP8266) and compares it to the current version of the code (pgmVersion). If they are different, then I know that I have a new version of the code. This is then followed by a write to EEPROM to save the current version pgmVersion so that the next time I boot this version will be the old version.
When I run the code with only the for loop for the eeprom read, I can see that the saved version is different than the current version (and can also see when they are the same). This seems to work properly.
However, when I run the full code that includes the write to eeprom, the read for loop always indicates that the saved version matches the current version and does not execute the eeprom write for loop. This happens consistently even when I run with a new value for the current version. This is simply baffling to me. I can remove power and then power up again and the new version data has been saved to eeprom so it seems that it is really being written.
Can anyone see what is wrong with my code or explain why the eeprom seems to be written without going through my eeprom write for loop? I've read lots of posts and online documentation and still can't figure this out.
Jim
#include <EEPROM.h>
const String pgmVersion = "00.04";
void setup() {
Serial.begin(115200);
EEPROM.begin(6);
delay(500);
char eepData;
char pgmData;
bool pgmMatch = true;
for (unsigned int i = 0; i < pgmVersion.length(); i++)
{
eepData = char(EEPROM.read(i));
pgmData = pgmVersion.charAt(i);
Serial.print("eepData = ");
Serial.println(eepData);
Serial.print("pgmVersion[i] = ");
Serial.println(pgmData);
if (eepData == pgmData)
{
Serial.println("eepData matches pgmData at index " + String(i));
} else
{
Serial.println("eepData does NOT match pgmData at index " + String(i));
pgmMatch = false;
}
}
if (!pgmMatch)
{
Serial.println("Writing EEPROM");
for (unsigned int i = 0; i < pgmVersion.length(); i++)
{
pgmData = pgmVersion.charAt(i);
EEPROM.write(i,pgmData);
delay(10);
}
if (EEPROM.commit())
{
Serial.println("EEPROM successfully committed");
} else
{
Serial.println("ERROR! EEPROM commit failed");
}
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Ok, I've found out what's going on. The above code fails to work correctly as described in the original post when running under VS Code with PlatformIO. But works as it should when running under the Arduino IDE. (I did not originally post the #include <arduino.h> that is needed in that environment - my mistake!).
When running the code with the write loop included, it looks like the eeprom write gets executed before the write loop itself as when the saved pgm data and new pgm data are known to be different the comparison code says they are the same.
I tried just commenting out the line with the eeprom write for a case when the saved pgm data and new pgm data are known to be different. This resulted in the write loop being entered as it should (meaning it the code detected the saved and new pgm data were not the same).
So it looks like the VS Code version with PlatformIO reorders the code by hoisting the eeprom write somewhere or something with that effect. If that is actually the case, what is needed is a fix to some piece of platform code or some sort of barrier instruction to prevent this from happening. This is unfortunate as I do appreciate the extra function available in the VS Code / PlatformIO environment.
I'm debugging an app, but I need to know some values in the fly, I was wondering if there's a way to print a message in console like console.log using Javascript.
I appreciate the help.
print() is probably what you are looking for. Here's some more info on debugging in flutter.
You can use
print()
function or
debugPrint()
The debugPrint() function can print large outputs.
There are more helpful methods in import 'dart:developer' library and one of them is log().
example:
int i = 5;
log("Index number is: $i");
//output
[log] Index number is: 5
void log(String message, {DateTime time, int sequenceNumber, int level
= 0, String name = '', Zone zone, Object error, StackTrace stackTrace})
Emit a log event.
This function was designed to map closely to the logging information
collected by package:logging.
[message] is the log message
[time] (optional) is the timestamp
[sequenceNumber] (optional) is a monotonically increasing sequence number
[level] (optional) is the severity level (a value between 0 and 2000); see the package:logging Level class for an overview of the
possible values
[name] (optional) is the name of the source of the log message
[zone] (optional) the zone where the log was emitted
[error] (optional) an error object associated with this log event
[stackTrace] (optional) a stack trace associated with this log event
Read more.:
print() is from dart:core and its implementation:
/// Prints a string representation of the object to the console.
void print(Object object) {
String line = "$object";
if (printToZone == null) {
printToConsole(line);
} else {
printToZone(line);
}
}
debugPrint():
/// Prints a message to the console, which you can access using the "flutter"
/// tool's "logs" command ("flutter logs").
///
/// If a wrapWidth is provided, each line of the message is word-wrapped to that
/// width. (Lines may be separated by newline characters, as in '\n'.)
///
/// By default, this function very crudely attempts to throttle the rate at
/// which messages are sent to avoid data loss on Android. This means that
/// interleaving calls to this function (directly or indirectly via, e.g.,
/// [debugDumpRenderTree] or [debugDumpApp]) and to the Dart [print] method can
/// result in out-of-order messages in the logs
// read more here: https://api.flutter.dev/flutter/foundation/debugPrint.html
DebugPrintCallback debugPrint = debugPrintThrottled;
/// Alternative implementation of [debugPrint] that does not throttle.
/// Used by tests.
debugPrintSynchronously(String message, { int wrapWidth })
/// Implementation of [debugPrint] that throttles messages. This avoids dropping
/// messages on platforms that rate-limit their logging (for example, Android).
void debugPrintThrottled(String message, { int wrapWidth })
Read more.
Note that only the print() is taking any type and print to the console. debugPrint() and log() only take String. So, you have to add .toString() or use string interpolation like I shown in provided example snippet.
I tend to do something similar to this
Foo foo;
try{
foo = _someMethod(); //some method that returns a new object
} catch (e) {
print('_someMethod: Foo Error ${foo.id} Error:{e.toString()}'); /*my custom error print message. You don't need brackets if you are printing a string variable.*/
}
Use debug print to avoid logging in production application.
debugPrint("Message");
You can also disable or change debug print implementation in main.dart or any other file like this:
debugPrint = (String message, {int wrapWidth})
{
debugPrintThrottled(message);//Or another other custom code
};
print, debugPrint and others have got some word limit restrictions, if you have something long to print on console, you can:
Create this method:
void printWrapped(String text) {
final pattern = RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}
Usage:
printWrapped("Your very long string ...");
Source
One more answer for Concatenate with String:
// Declaration
int number = 10;
//Button Action
RaisedButton(
child: Text("Subtract Me"),
onPressed: () {
number = number - 1;
print('You have got $number as result');
print('Before Value is ${number - 1} and After value is ${number + 1}');
},
),
//Output:
flutter: You have got 9 as result
flutter: Before Value is 8 and After value is 10
debugPrint()
Might as well use rather than print() as it attempts to reduce log line drop or being out of order on Android kernel
Refs:
Logging in Flutter
I think this might help you, because, I was also got stuck in many ways of knowing the output of my code in the dart file, hence I got the solution by following the steps, shown in the video.
https://www.youtube.com/watch?v=hhP1tE-IHos
here I have shown an instance of how it works after following the video.
check the left side column where it shows about the value which profile variable carry i.e., null
you can simply use print('whatever you want to print') same as console.log() in javascript.
for more info you can check here.
Note that the print() and log() options both add their own labels at the start of the line, and apply additional formatting that can cause long lines to be truncated. In the case of a dart:io app, you can bypass this interception and mangling entirely by going directly to stdout/stderr, etc. as in stdout.write(), stdout.writeln(), etc. Likewise if you are looking to log explicitly to one or the other. I ran into this issue when adding CLI args to a flutter application.
I use something like this. The print() function can print data up to some limit. So I use this log.
import 'dart:developer';
debugLog({String tag = '', required dynamic value}) {
log("TAG $tag : ${value.toString()}");
}
I am wondering how to continue using stdin in D after the program has read an unsuitable value. (for example, letters when it was expecting an int)
I wrote this to test it:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
}
}
writeln(a);
}
After entering incorrect values such as 'b', the program would print out the message indefinitly. I also examined the exception which indicated that it was trying to read the same characters again, so I made a version like this:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
char c;
readf("%c", c);
}
}
writeln(a);
}
Which still threw an exception when trying to read a, but not c. I also tried using stdin.clearerr(), which had no effect. Does anyone know how to solve this? Thanks.
My recommendation: don't use readf. It is so bad. Everyone goes to it at first since it is in the stdlib (and has been since 1979 lol, well scanf has... and imo i think scanf is better than readf! but i digress), and almost everyone has trouble with it. It is really picky about formats and whitespace consumption when it goes right, and when it goes wrong, it gives crappy error messages and leaves the input stream in an indeterminate state. And, on top of that, is still really limited in what data types it can actually read in and is horribly user-unfriendly, not even allowing things like working backspacing on most systems!
Slightly less bad than readf is to use readln then strip and to!int it once you check the line and give errors. Something like this:
import std.stdio;
import std.string; // for strip, cuts off whitespace
import std.algorithm.searching; // for all
import std.ascii; // for isAscii
import std.conv; // for to, does string to other type conversions
int readInt() {
for(;;) {
string line = stdin.readln();
line = line.strip();
if(all!isDigit(line))
return to!int(line);
else
writeln("Please enter a number");
}
assert(0);
}
void main()
{
int a = readInt();
writeln(a);
}
I know that's a lot of import spam (and for a bunch of individual trivial functions too), and readln still sucks for the end user, but this little function is going to be so much nicer on your users and on yourself than trying to use readf. It will consistently consume one line at a time and give a nice message. Moreover, the same pattern can be extended to any other type of validation you need, and the call to readln can be replaced by a call to a more user-friendly function that allows editing and history and stuff later if you decide to go down that route.
If you must use readf anyway though, easiest way to make things sane again in your catch block is still to just call readln and discard its result. So then it just skips the whole line containing the error, allowing your user to start fresh. That'd also drop if they were doing "1 2" and wanted two ints to be read at once... but meh, I'd rather start them fresh anyway than try to pick up an errored line half way through.
Can someone post a simple example of subclassing FileBasedSource? I'm new to Google Dataflow and very inexperienced with Java. My goal is to read files while including line numbers as a key, or to skip lines based on the line number.
The implementation of XMLSource is a good starting point for understanding how FileBasedSource works. You'll likely want something like this for your reader (where readNextLine() reads to the end of a line and updates the offset):
protected void startReading(ReadableByteChannel channel) throws IOException {
if (getCurrentSource().getMode() == FileBasedSource.Mode.SINGLE_FILE_OR_SUBRANGE) {
// If we are not at the beginning of a line, we should ignore the current line.
if (getCurrentSource().getStartOffset() > 0) {
SeekableByteChannel seekChannel = (SeekableByteChannel) channel;
// Start from one character back and read till we find a new line.
seekChannel.position(seekChannel.position() - 1);
nextOffset = seekChannel.position() + readNextLine(new ByteArrayOutputStream());
}
}
}
I've created a gist with the complete LineIO example, which may be simpler than XMLSource.
I'd like my Dart program to print to the dev console of my browser. How can I print to the console (DevTools's console, for example) ?
Use print() to print a string to the console of your browser:
import 'dart:html';
main() {
var value = querySelector('input').value;
print('The value of the input is: $value');
}
You will see a message printed to the developer console.
If you simlpy want to print text to the console you can use print('Text').
But if you want to access the advanced fatures of the DevTools console you need to use the Console class from dart:html: Console.log('Text').
It supports printing on different levels (info, warn, error, debug). It also allows to print tables and other more advanced features. Note that these are not supported in every browser! It's sad that the documentation about the Console class is incomplete, but you can take a look at the documentation of Chrome here and here.
There is log() from import 'dart:developer' library also.
example:
int name = "Something";
log("ClassName: successfully initialized: $name");
//output
[log] ClassName: successfully initialized: Something
Please note that log and debugPrint taking a value of String not like print. So, you have to add .toString() at the end or use with String interpolation like I used in above example.
From doc:
You have two options for logging for your application. The first is to
use stdout and stderr. Generally, this is done using print()
statements, or by importing dart:io and invoking methods on stderr and
stdout. For example:
stderr.writeln('print me');
If you output too much at once, then Android sometimes discards some
log lines. To avoid this, use debugPrint(), from Flutter’s foundation
library. This is a wrapper around print that throttles the output to a
level that avoids being dropped by Android’s kernel.
The other option for application logging is to use the dart:developer
log() function. This allows you to include a bit more granularity and
information in the logging output. Here’s an example:
import 'dart:developer' as developer;
void main() {
developer.log('log me', name: 'my.app.category');
developer.log('log me 1', name: 'my.other.category');
developer.log('log me 2', name: 'my.other.category');
}
You can also pass application data to the log call. The convention for
this is to use the error: named parameter on the log() call, JSON
encode the object you want to send, and pass the encoded string to the
error parameter.
import 'dart:convert'; import 'dart:developer' as developer;
void main() {
var myCustomObject = ...;
developer.log(
'log me',
name: 'my.app.category',
error: jsonEncode(myCustomObject),
);
}
If viewing the logging output in DevTool’s logging view, the JSON
encoded error param is interpreted as a data object and rendered in
the details view for that log entry.
read more(It's cool like a tutorial).
If you are here for Flutter, there's debugPrint which you should use.
Here's the doc text for the same.
/// Prints a message to the console, which you can access using the "flutter"
/// tool's "logs" command ("flutter logs").
/// By default, this function very crudely attempts to throttle the rate at
/// which messages are sent to avoid data loss on Android. This means that
/// interleaving calls to this function (directly or indirectly via, e.g.,
/// [debugDumpRenderTree] or [debugDumpApp]) and to the Dart [print] method can
/// result in out-of-order messages in the logs.
You might get SDK version constraint as it is only for 2.2 and above.
Dart print() function works differently in different environment.
print() when used in console based application it outputs in the terminal console
print() when used in web based application it outputs to the developer console.
void main() {
print("HTML WebApp");
}
The only way I know , which is supported by dartpad ,is through using print();
by the way Dart uses the ${} syntax for expressions, or just a $ for single value.
ex:-
int x=3;
print('hello world') ;
print(x) ;
print('x = $x') ;
and her is the link for the documentation
print method!