Edit local yaml file in rust - rust

I'm trying to edit yaml file using serde_yaml but using this i'm only able to edit in stdout but cannot write back to local file(/home/home/.kube/config)
let kubeconfig = "/home/home/.kube/config"
let contents = fs::read_to_string(kubeconfig)
.expect("Something went wrong reading the file");
let mut value: serde_yaml::Value = serde_yaml::from_str(&contents).unwrap();
*value.get_mut("current-context").unwrap() = "new_user".into();
// Below lines shows the edited file in stdout
serde_yaml::to_writer(std::io::stdout(), &value).unwrap();
I did tired as below an other method but had no luck.
let writer = serde_yaml::to_writer(std::io::stdout(), &value).unwrap();
println!("{:?}",writer); // shows ()
serde_yaml::to_writer(writer);
How do i write this edit back to /home/home/.kube/config ?

It seems that you are trying to use to_writer as to_string:
let writer = serde_yaml::to_string(&value).unwrap();
println!("{:?}", writer);
Then you can save the string how you usually would.
Or, alternatively, you could write directly to a file:
let mut file = File::create("/home/home/.kube/config").unwrap();
serde_yaml.to_writer(&mut file, &value);

Related

How to write a String to file? [duplicate]

This question already has answers here:
What's the de-facto way of reading and writing files in Rust 1.x?
(3 answers)
Closed 6 months ago.
I am very new to Rust, and have the question, how to write a string to a file in Rust. There are plenty of tutorials and documentations out there, how to write an &str type to file, but no tutorial how to write a String type to files. I wrote this code by myself and it compiles, but I always get an "Bad file descriptor (os error 9)". I'm on Linux(Manjaro).
I'm very thankfully for every help I will get.
//Import
use std::fs::File;
use std::io::*;
//Mainfunction
fn main() {
//Programm startet hier | program starts here
println!("Program started...");
// Lesen des Files, createn des Buffers | reading file createing buffer
let mut testfile = File::open("/home/julian/.rust_test/test_0.txt").unwrap();
let mut teststring = String::from("lol");
//Vom File auf den Buffer schreiben | writing from file to buffer
testfile.read_to_string(&mut teststring).unwrap();
//Buffer ausgeben | print to buffer
println!("teststring: {}", teststring);
// Neue Variable deklarieren | declare new variable
let msg = String::from("Writetest tralalalal.");
// msg an ursprünglichen String anhängen | append msg to string
teststring.push_str(&msg);
println!("teststring: {}", teststring);
// Neuen String nach File schreiben | write new sting to file
let eg = testfile.write_all(&teststring.as_bytes());
match eg {
Ok(()) => println!("OK"),
Err(e) => println!("{}",e)
}
println!("Fertig")
}
Your issue is that the file you opened is opened in read-only mode.
As #Herohtar correctly pointed out, from the documentation of File::open():
Attempts to open a file in read-only mode.
What you are trying to do requires read & write mode. There is no pre-made function for that, so you need to build your own using OpenOptions:
//Import
use std::fs::OpenOptions;
use std::io::*;
//Mainfunction
fn main() {
//Programm startet hier | program starts here
println!("Program started...");
// Lesen des Files, createn des Buffers | reading file createing buffer
let mut testfile = OpenOptions::new()
.read(true)
.write(true)
.open("test_0.txt")
.unwrap();
let mut teststring = String::from("lol");
//Vom File auf den Buffer schreiben | writing from file to buffer
testfile.read_to_string(&mut teststring).unwrap();
//Buffer ausgeben | print to buffer
println!("teststring: {}", teststring);
// Neue Variable deklarieren | declare new variable
let msg = String::from("Writetest tralalalal.");
// msg an ursprünglichen String anhängen | append msg to string
teststring.push_str(&msg);
println!("teststring: {}", teststring);
// Neuen String nach File schreiben | write new sting to file
let eg = testfile.write_all(teststring.as_bytes());
match eg {
Ok(()) => println!("OK"),
Err(e) => println!("{:?}", e),
}
println!("Fertig")
}
The rest of your code is pretty much fine.
The only nitpick I have is that testfile.write_all(&teststring.as_bytes()) doesn't make much sense, because as_bytes() already returns a reference, so I removed the & from it.

Create web_sys::RtcPeerConnection with customized configuration

I am trying to figure how to create a RtcPeerConnection with the web-sys crate. In JavaScript I can write the following:
const pc = new RTCPeerConnection({'iceServers': [{'urls': ['stun:stun.l.google.com:19302']}]});
How does this translate to rust? I have tried the following:
let mut rtc = RtcConfiguration::new();
let config = RtcConfiguration::ice_servers(&mut rtc, &JsValue::from_serde(&json!({"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]})).unwrap());
let pc = RtcPeerConnection::new_with_configuration(&config).unwrap();
But it fails when creating pc. The json! macro is from serde_json::json.
For anyone with the same issue, the following works:
let mut rtc = RtcConfiguration::new();
let config = rtc.ice_servers(&JsValue::from_serde(&json!([{"urls": "stun:stun.l.google.com:19302"}])).unwrap());
let pc = RtcPeerConnection::new_with_configuration(&config).unwrap();

Is it possible to access current file name?

Is it possible to access current file name in Rust by
// main.rs
fn main() {
println!("filename: {}", FILE_NAME);
}
?
(This program should print filename: main.rs)
You can use the std::file macro to get the current source filename at the compile time.
let this_file = file!();
If you want to remove the path from the returned filename, you can construct a Path with it and call the file_name method.
let filename_only = Path::new(this_file).file_name().and_then(|s| s.to_str()).unwrap();
Playground

Command panics with process cannot access the file already being used

I'm trying to spawn a CLI in my Rust code via Comand::new. CLI file is extracting from binary files to exe file and then run with Command::new. But It gives 'ERROR: Os { code: 32, kind: Other, message: "The process cannot access the file because it is being used by another process." }' error.
let taskmgr_pid = get_pid_by_name("Taskmgr.exe");
let process_hide = asset::Asset::get("cli.exe").unwrap();
let file_path = "C:\\filepathhere\\cli.exe";
let mut file = File::create(file_path.to_string()).expect("Couldn't create file");
file.write_all(&process_hide);
let res = Command::new(file_path)
.arg(taskmgr_pid.to_string())
.output()
.expect("ERROR");
println!("PID: {}", taskmgr_pid);
println!("{:?}", res);
It's because you didn't close file prior to executing the command. The easiest way to resolve the issue, is to simply drop(file); prior to Command::new().
let mut file = File::create(file_path).expect("unable to create file");
file.write_all(&process_hide).expect("unable to write");
drop(file);
let res = Command::new(file_path)
.arg(taskmgr_pid.to_string())
.output()
.expect("ERROR");

Reading file using Node.js "Invalid Encoding" Error

I am creating an application with Node.js and I am trying to read a file called "datalog.txt." I use the "append" function to write to the file:
//Appends buffer data to a given file
function append(filename, buffer) {
let fd = fs.openSync(filename, 'a+');
fs.writeSync(fd, str2ab(buffer));
fs.closeSync(fd);
}
//Converts string to buffer
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
append("datalog.txt","12345");
This seems to work great. However, now I want to use fs.readFileSync to read from the file. I tried using this:
const data = fs.readFileSync('datalog.txt', 'utf16le');
I changed the encoding parameter to all of the encoding types listed in the Node documentation, but all of them resulted in this error:
TypeError: Argument at index 2 is invalid: Invalid encoding
All I want to be able to do is be able to read the data from "datalog.txt." Any help would be greatly appreciated!
NOTE: Once I can read the data of the file, I want to be able to get a list of all the lines of the file.
Encoding and type are an object:
const data = fs.readFileSync('datalog.txt', {encoding:'utf16le'});
Okay, after a few hours of troubleshooting a looking at the docs I figured out a way to do this.
try {
// get metadata on the file (we need the file size)
let fileData = fs.statSync("datalog.txt");
// create ArrayBuffer to hold the file contents
let dataBuffer = new ArrayBuffer(fileData["size"]);
// read the contents of the file into the ArrayBuffer
fs.readSync(fs.openSync("datalog.txt", 'r'), dataBuffer, 0, fileData["size"], 0);
// convert the ArrayBuffer into a string
let data = String.fromCharCode.apply(null, new Uint16Array(dataBuffer));
// split the contents into lines
let dataLines = data.split(/\r?\n/);
// print out each line
dataLines.forEach((line) => {
console.log(line);
});
} catch (err) {
console.error(err);
}
Hope it helps someone else with the same problem!
This works for me:
index.js
const fs = require('fs');
// Write
fs.writeFileSync('./customfile.txt', 'Content_For_Writing');
// Read
const file_content = fs.readFileSync('./customfile.txt', {encoding:'utf8'}).toString();
console.log(file_content);
node index.js
Output:
Content_For_Writing
Process finished with exit code 0

Resources