I'm trying to read a text file in an Arduino SD card reader and copy its text into a string variable, but the function .read always returns -1. How can I solve this problem?
Here's the code:
#include <SPI.h>
#include <SD.h>
File mappa;
String text;
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
mappa = SD.open("map.txt");
// if the file opened okay, write to it:
if (mappa) {
Serial.println("File aperto");
} else {
// if the file didn't open, print an error:
Serial.println("error opening map.txt");
}
Serial.println("map.txt:");
// read from the file until there's nothing else in it:
while (mappa.available()) {
Serial.write(mappa.read());
// text = parseInt(mappa.read());
}
Serial.println(text);
// close the file:
mappa.close();
}
void loop() {
// nothing happens after setup
}
I know that .read() returns an array of integers, but I don't know how to access them separately.
After further research, I got how .read works: It reads the character its cursor is pointing at while advancing the cursor.
So, in order to read the entirety of the file you have to remove the Serial.write portion and convert the characters into char:
String finalString = "";
while (mappa.available())
{
finalString += (char)mappa.read();
}
I'm exporting MIME eMails with the following code:
public String fromRawMime(final Session s, final Document doc) throws NotesException {
final Stream notesStream = s.createStream();
final MIMEEntity rootMime = doc.getMIMEEntity();
// check if it is multi-part or single
if (rootMime.getContentType().equals("multipart")) {
this.printMIME(rootMime, notesStream);
} else {
// We can just write the content into the
// Notes stream to get the bytes
rootMime.getEntityAsText(notesStream);
}
// Write it out
notesStream.setPosition(0);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.append(notesStream.read());
notesStream.close();
notesStream.recycle();
rootMime.recycle();
return out.toString();
}
// Write out a mime entry to a Stream object, includes sub entries
private void printMIME(final MIMEEntity mimeRoot, final Stream out) throws NotesException {
if (mimeRoot == null) {
return;
}
// Encode binary as base64
if (mimeRoot.getEncoding() == MIMEEntity.ENC_IDENTITY_BINARY) {
mimeRoot.decodeContent();
mimeRoot.encodeContent(MIMEEntity.ENC_BASE64);
}
out.writeText(mimeRoot.getBoundaryStart(), Stream.EOL_NONE);
mimeRoot.getEntityAsText(out);
out.writeText(mimeRoot.getBoundaryEnd(), Stream.EOL_NONE);
if (mimeRoot.getContentType().equalsIgnoreCase("multipart")) {
// Print preamble if it isn't empty
final String preamble = mimeRoot.getPreamble();
if (!preamble.isEmpty()) {
out.writeText(preamble, Stream.EOL_NONE);
}
// Print content of each child entity - recursive calls
// Include recycle of mime elements
MIMEEntity mimeChild = mimeRoot.getFirstChildEntity();
while (mimeChild != null) {
this.printMIME(mimeChild, out);
final MIMEEntity mimeNext = mimeChild.getNextSibling();
// Recycle to ensure we don't bleed memory
mimeChild.recyle();
mimeChild = mimeNext;
}
}
}
The result contains one empty line for each line. Including the content that gets added using getEntityAsText. What am I missing to get rid of the extra lines?
The email RFCs require the use of CRLF to terminate text lines.
You are using EOL_NONE, so the writeText method isn't adding anything to the text, but apparently both the CR and LF are being treated as newlines in your output. You may want to try using out.writeText with EOL_PLATFORM instead.
The devils is in the details...
the printMIME function works just fine. Changing the EOL didn't have an impact. However I added EOL_PLATFORM later on for the final result to separate the headers from the content.
The offending code is this:
notesStream.setPosition(0);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.append(notesStream.read());
notesStream.close();
Turns out that it seems to interpret whatever was in the MIME as 2 line feeds. So the code needs to be changed to:
notesStream.setPosition(0);
String out = notesStream.readText();
notesStream.close();
so instead of a OutputStream I needed a String and instead of read() I needed readText(). Now working happily in my "project castle"
I'm currently experimenting with sending a string to my Arduino Yun and trying to get it to reply back depending on what I send it.
I picked up a framework of some code here and have been experimenting with it but apart from the serial monitor displaying 'ready' I can't make it go any further.
The code is:
//declace a String to hold what we're inputting
String incomingString;
void setup() {
//initialise Serial communication on 9600 baud
Serial.begin(9600);
while(!Serial);
//delay(4000);
Serial.println("Ready!");
// The incoming String built up one byte at a time.
incomingString = "";
}
void loop () {
// Check if there's incoming serial data.
if (Serial.available() > 0) {
// Read a byte from the serial buffer.
char incomingByte = (char)Serial.read();
incomingString += incomingByte;
// Checks for null termination of the string.
if (incomingByte == '\0') {
// ...do something with String...
if(incomingString == "hello") {
Serial.println("Hello World!");
}
incomingString = "";
}
}
}
Can anyone point me in the right direction?
Thanks
I suspect the problem is that you're adding the null terminator onto the end of your string when you do: incomingString += incomingByte. When you're working with string objects (as opposed to raw char * strings) you don't need to do that. The object will take care of termination on its own.
The result is that your if condition is effectively doing this: if ("hello\0" == "hello") .... Obviously they're not equal, so the condition always fails.
I believe the solution is just to make sure you don't append the byte if it's null.
Try This:
String IncomingData = "";
String Temp = "";
char = var;
void setup()
{
Serial.begin(9600);
//you dont have to use it but if you want
// if(Serial)
{
Serial.println("Ready");
}
//or
while(!Serial)
{delay(5);}
Serial.println("Ready");
void loop()
{
while(Serial.available())
{
var = Serial.read();
Temp = String(var);
IncomingData+= Temp;
//or
IncomingData.concat(Temp);
// you can try
IncomindData += String(var);
}
Serial.println(IncomingData);
IncomingData = "";
}
I'm developing an app where I need to send the values of 3 seekbars via bluetooth. All the bluetooth method I've developed is based on the bluetoothChat example. The app communicates well sending characters, but as i said, i need to send the value of 3 seekbars.
So, I'm creating a sending function to send these 3 values in one string, but i think that i'm doing wrong the cast because i'm getting an error and the logcat refers my to this point.
This is the code, need to mention that the "savedProgressX" values are int type and have the current value of the seekbar, and the "sendX" values are textview type that I've created only to save these values:
public void sendValues() {
send1 = Integer.toString(savedProgress1);
send2 = Integer.toString(savedProgress2);
send3 = Integer.toString(savedProgress3);
/**Set the seekbars values into a string*/
String message = send1+":"+send2+":"+send3+"\n";
//String[] values = message.split(":");
//for (String value : values) {
//int number = Integer.valueOf(value);
//}
/**Check that we're actually connected before trying anything*/
if (GlobalVar.mTransmission.getState() != GlobalVar.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
/**Get the message bytes and tell the Transmission to write*/
byte[] send = message.getBytes();
GlobalVar.mTransmission.write(send);
/**Reset out string buffer to zero*/
GlobalVar.mOutStringBuffer.setLength(0);
}
Using C# 4 in a Windows console application that continually reports progress how can I make the "redraw" of the screen more fluid?
I'd like to do one of the following:
- Have it only "redraw" the part of the screen that's changing (the progress portion) and leave the rest as is.
- "Redraw" the whole screen but not have it flicker.
Currently I re-write all the text (application name, etc.). Like this:
Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0"), total.ToString("N0"), (count / (decimal)total).ToString("P2")));
Which causes a lot of flickering.
Try Console.SetCursorPosition. More details here: How can I update the current line in a C# Windows Console App?
static void Main(string[] args)
{
Console.SetCursorPosition(0, 0);
Console.Write("################################");
for (int row = 1; row < 10; row++)
{
Console.SetCursorPosition(0, row);
Console.Write("# #");
}
Console.SetCursorPosition(0, 10);
Console.Write("################################");
int data = 1;
System.Diagnostics.Stopwatch clock = new System.Diagnostics.Stopwatch();
clock.Start();
while (true)
{
data++;
Console.SetCursorPosition(1, 2);
Console.Write("Current Value: " + data.ToString());
Console.SetCursorPosition(1, 3);
Console.Write("Running Time: " + clock.Elapsed.TotalSeconds.ToString());
Thread.Sleep(1000);
}
Console.ReadKey();
}
I know this question is a bit old but I found if you set Console.CursorVisible = false then the flickering stops as well.
Here's a simple working demo that shows multi-line usage without flickering. It shows the current time and a random string every second.
private static void StatusUpdate()
{
var whiteSpace = new StringBuilder();
whiteSpace.Append(' ', 10);
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var randomWord = new string(Enumerable.Repeat(chars, random.Next(10)).Select(s => s[random.Next(s.Length)]).ToArray());
while (true)
{
Console.SetCursorPosition(0, 0);
var sb = new StringBuilder();
sb.AppendLine($"Program Status:{whiteSpace}");
sb.AppendLine("-------------------------------");
sb.AppendLine($"Last Updated: {DateTime.Now}{whiteSpace}");
sb.AppendLine($"Random Word: {randomWord}{whiteSpace}");
sb.AppendLine("-------------------------------");
Console.Write(sb);
Thread.Sleep(1000);
}
}
The above example assumes your console window is blank to start. If not, make sure to use Console.Clear() first.
Technical Note:
SetCursorPosition(0,0) places the cursor back to the top (0,0) so the next call to Console.Write will start from line 0, char 0. Note, it doesn't delete the previous content before writing. As an example, if you write "asdf" over a previous line such as "0123456", you'll end up with something like "asdf456" on that line. For that reason, we use a whiteSpace variable to ensure any lingering characters from the previous line are overwritten with blank spaces. Adjust the length of the whiteSpace variable to meet your needs. You only need the whiteSpace variable for lines that change.
Personal Note:
For my purposes, I wanted to show the applications current status (once a second) along with a bunch of other status information and I wanted to avoid any annoying flickering that can happen when you use Console.Clear(). In my application, I run my status updates behind a separate thread so it constantly provides updates even though I have numerous other threads and long running tasks going at the same time.
Credits:
Thanks to previous posters and dtb for the random string generator used in the demo.
How can I generate random alphanumeric strings in C#?
You could try to hack something together using the core libraries.
Rather than waste your time for sub-standard results, I would check out this C# port of the ncurses library (which is a library used for formatting console output):
Curses Sharp
I think you can use \r in Windows console to return the beginning of a line.
You could also use SetCursorPosition.
I would recommend the following extension methods. They allow you to use a StringBuilder to refresh the console view without any flicker, and also tidies up any residual characters on each line
The Problem: The following demo demonstrates using a standard StringBuilder, where updating lines that are shorter than the previously written line get jumbled up. It does this by writing a short string, then a long string on a loop:
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLine("Short msg");
else
sb.AppendLine("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
The Solution: By using the extension method provided below, the issue is resolved
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLineEx("Short msg");
else
sb.AppendLineEx("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
Extension Methods:
public static class StringBuilderExtensions
{
/// <summary>
/// Allows StrinbBuilder callers to append a line and blank out the remaining characters for the length of the console buffer width
/// </summary>
public static void AppendLineEx(this StringBuilder c, string msg)
{
// Append the actual line
c.Append(msg);
// Add blanking chars for the rest of the buffer
c.Append(' ', Console.BufferWidth - msg.Length - 1);
// Finish the line
c.Append(Environment.NewLine);
}
/// <summary>
/// Combines two StringBuilders using AppendLineEx
/// </summary>
public static void AppendEx(this StringBuilder c, StringBuilder toAdd)
{
foreach (var line in toAdd.ReadLines())
{
c.AppendLineEx(line);
}
}
/// <summary>
/// Hides the console cursor, resets its position and writes out the string builder
/// </summary>
public static void UpdateConsole(this StringBuilder c)
{
// Ensure the cursor is hidden
if (Console.CursorVisible) Console.CursorVisible = false;
// Reset the cursor position to the top of the console and write out the string builder
Console.SetCursorPosition(0, 0);
Console.WriteLine(c);
}
}
I actually had this issue so I made a quick simple method to try and eliminate this.
static void Clear(string text, int x, int y)
{
char[] textChars = text.ToCharArray();
string newText = "";
//Converts the string you just wrote into a blank string
foreach(char c in textChars)
{
text = text.Replace(c, ' ');
}
newText = text;
//Sets the cursor position
Console.SetCursorPosition(x, y);
//Writes the blank string over the old string
Console.WriteLine(newText);
//Resets cursor position
Console.SetCursorPosition(0, 0);
}
It actually worked surprisingly well and I hope it may work for you!
Naive approach but for simple applications is working:
protected string clearBuffer = null; // Clear this if window size changes
protected void ClearConsole()
{
if (clearBuffer == null)
{
var line = "".PadLeft(Console.WindowWidth, ' ');
var lines = new StringBuilder();
for (var i = 0; i < Console.WindowHeight; i++)
{
lines.AppendLine(line);
}
clearBuffer = lines.ToString();
}
Console.SetCursorPosition(0, 0);
Console.Write(clearBuffer);
Console.SetCursorPosition(0, 0);
}
Console.SetCursorPosition(0, 0); //Instead of Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0")