Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)
I want to copy file in this way:
file 1:
a
b
c
file 2:
c
b
a
--
Ground21____________\\
ground21@pocztaKROPKAfm 24 3170
Ground21 wrote:
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)
I want to copy file in this way:
file 1:
a
b
c
file 2:
c
b
a
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should work
ok.
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should work
ok.
I think I wrote bad example:
Once more:
file1:
text1
text2
text3
abctest
file2:
abctest
text3
text2
text1
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 wrote:
>
>The easiest way would be to read all the lines into something like an std::vector<std::string, then write the new file iterating backwards through the vector. As long as you don't have huge files, this should work ok.
I think I wrote bad example:
I did understand your posting anyway.
Once more:
file1:
text1
text2
text3
abctest
file2:
abctest
text3
text2
text1
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.
Rolf Magnus napsal:
Ground21 wrote:
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should
work ok.
I think I wrote bad example:
I did understand your posting anyway.
Once more:
file1:
text1
text2
text3
abctest
file2:
abctest
text3
text2
text1
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.
I would recommend std::list instead of std::vector, because list can be
simplier (== more effectively) extended in length.
Ondra Holub wrote:
Rolf Magnus napsal:
>Ground21 wrote:
>>>The easiest way would be to read all the lines into something like an std::vector<std::string, then write the new file iterating backwards through the vector. As long as you don't have huge files, this should work ok. I think I wrote bad example:
I did understand your posting anyway.
>>Once more:
file1:
text1 text2 text3 abctest
file2:
abctest text3 text2 text1
Yup. What you should do is read the file line by line and put each line as a separate string into a vector. So later you have a vector of lines. Then you can iterate through that vector backwards and write the strings out again.
I would recommend std::list instead of std::vector, because list can be
simplier (== more effectively) extended in length.
I used deque.
I tried to be real clever, with reverse_copy on an istream_iterator, and
an ostream_iterator, but reverse_copy requires Bidirectional Iterators. :(
Rolf Magnus napisał(a):
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.
can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...
#include <vector.h>
vector <char*tab(10);
tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 wrote:
Rolf Magnus napisał(a):
>Yup. What you should do is read the file line by line and put each line as a separate string into a vector. So later you have a vector of lines. Then you can iterate through that vector backwards and write the strings out again.
can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...
#include <vector.h>
vector <char*tab(10);
tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}
Lets see...
1. What is "lines"?
2. What happens if there are more than 10 lines in a file?
3. What happens if a line is bigger than 256?
4. Why are you using arrays and C-style I/O?
5. What is <vector.h>? The C++ header is <vector>
6. Every entry in your vector is identical, since you're storing the
same address over and over.
And that's just off the top of my head.
red floyd napisał(a):
1. What is "lines"?
int lines=0;
fseek(fileh,0L,SEEK_SET);
while(feof(fileh)==0) if(fgetc(fileh)=='\n') linies++;
lines - number of lines in my text file.
2. What happens if there are more than 10 lines in a file?
I read in wikibooks, that value of size will automaticlly increase if
necessary...
3. What happens if a line is bigger than 256?
I know, that it can be done better using something like strlen to check
line lenght, but for me, 256 is OK.
4. Why are you using arrays and C-style I/O?
5. What is <vector.h>? The C++ header is <vector>
in c++ builder 6 it works the same for <vectorand <vector.h>...
6. Every entry in your vector is identical, since you're storing the
same address over and over.
I though, that I take first line to tab[0], second line to tab[1]...
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 wrote:
>
can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...
#include <vector.h>
vector <char*tab(10);
tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}
It's a bad mix of C and C++, besides the "Access violation".
// reading a file line by line
std::ifstream ifs ("tmp.txt");
std::string line;
std::vector<std::stringlines;
while (getline (ifs, line)) {
lines.push_back(line);
}
Is this already in the C++ FAQ?
Ground21 wrote:
red floyd napisał(a):
>1. What is "lines"?
int lines=0;
fseek(fileh,0L,SEEK_SET);
while(feof(fileh)==0) if(fgetc(fileh)=='\n') linies++;
lines - number of lines in my text file.
>2. What happens if there are more than 10 lines in a file?
I read in wikibooks, that value of size will automaticlly increase if
necessary...
Yes, if you use the push_back member function.
>3. What happens if a line is bigger than 256?
I know, that it can be done better using something like strlen to check
line lenght, but for me, 256 is OK.
It would be better as well as easier to use std::string instead of raw char
arrays and pointers.
>4. Why are you using arrays and C-style I/O? 5. What is <vector.h>? The C++ header is <vector>
in c++ builder 6 it works the same for <vectorand <vector.h>...
Well, then you better stick to the standard header <vector>, otherwise your
program will be non-portable.
>6. Every entry in your vector is identical, since you're storing the same address over and over.
I though, that I take first line to tab[0], second line to tab[1]...
You could try something based on this (untested):
#include <istream>
#include <ostream>
#include <string>
#include <vector>
void reverse_copy_file(std::istream& infile, std::ostream& outfile)
{
typedef std::vector<std::string vec_type;
vec_type text;
std::string line;
while (std::getline(infile, line))
text.push_back(line);
vec_type::const_reverse_iterator it = text.rbegin(), end = text.rend();
for (; it != end; ++it)
outfile << line << '\n';
}
r wrote:
// reading a file line by line
std::ifstream ifs ("tmp.txt");
std::string line;
std::vector<std::stringlines;
while (getline (ifs, line)) {
lines.push_back(line);
}
Is this already in the C++ FAQ?
[C++ Error] zapis.cpp(136): E2285 Could not find a match for
'getline<_CharT,_Traits,_Alloc>(FILE *,string)'
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 wrote:
r wrote:
>// reading a file line by line std::ifstream ifs ("tmp.txt"); std::string line; std::vector<std::stringlines; while (getline (ifs, line)) { lines.push_back(line); }
Is this already in the C++ FAQ?
[C++ Error] zapis.cpp(136): E2285 Could not find a match for
'getline<_CharT,_Traits,_Alloc>(FILE *,string)'
That's because you didn't copy the whole example. He used an ifstream
for input, not a FILE*.
Use C++ style I/O if you're writing C++.
Ground21 wrote in message ...
>Rolf Magnus napisał(a):
>Yup. What you should do is read the file line by line and put each line as
a
>separate string into a vector. So later you have a vector of lines. Then you can iterate through that vector backwards and write the strings out again.
can You tell me what's wrong with this code?: (I want to save lines from file 'file' to vectors, and then, write them into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem with char*...
// >#include <vector.h>
#include <vector// C++
>vector <char*tab(10);
tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++){
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--){
fputs(tab[i],tmp);
}
#include <vector// C++
#include <string>
#include <fstream>
#include <algorithm>
int main(){
std::ifstream copin( "ZZtest.txt" );
if( not copin.is_open() ){ throw "a fit";}
std::vector<std::stringTmpFile;
for( std::string line; std::getline( copin, line ); ){
TmpFile.push_back(line);
}
// copin.close();
std::reverse( TmpFile.begin(), TmpFile.end() ); // reverse it
std::ofstream out( "ZZtestR.txt" );
for( size_t i(0); i < TmpFile.size(); ++i ){
std::reverse( TmpFile.at(i).begin(), TmpFile.at(i).end());
out<< TmpFile.at( i ) <<std::endl;
}
// out.close();
} // main()
// ----------
// - contents "ZZtest.txt" -
Record 0
Record 1
Record 2
Record 3
Record 4
Record 5
Record 6
// - contents "ZZtestR.txt" -
6 droceR
5 droceR
4 droceR
3 droceR
2 droceR
1 droceR
0 droceR
--
Bob R
POVrookie
Ground21 wrote:
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)
I want to copy file in this way:
file 1:
a
b
c
file 2:
c
b
a
I think the most simple solution would use a stack an C++ I/O.
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
using namespace std;
int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;
string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop();
}
return 0;
}
Tobias Gneist wrote:
Ground21 wrote:
>Hello. How could I read the whole text file line after line from the end of file? (I want to ~copy~ file)
I want to copy file in this way:
file 1:
a b c
file 2:
c b a
I think the most simple solution would use a stack an C++ I/O.
Hmm, right. A stack is actually a better choice than a vector.
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
using namespace std;
int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;
string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
Simpler and more correct than those last 5 lines would be:
while (in >s)
ss.push(s);
while (!ss.empty()) {
out << ss.top() << endl;
No need to flush the stream after each line, so '\n' instead of endl is
sufficient.
ss.pop();
}
return 0;
}
I think the most simple solution would use a stack an C++ I/O.
>
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
using namespace std;
int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;
string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
If input likes:
test
122 345 345
output would be:
345
345
122
test
How about this
while (std::getline(in,s)) {
ss.push(s);
}
output would be:
122 345 345
test
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop();
}
return 0;
}
gongzibi napisał(a):
How about this
while (std::getline(in,s)) {
ss.push(s);
}
output would be:
122 345 345
test
ifstream in("log.txt");
ofstream out("out.txt");
stack<stringss;
string s;
in >s;
while (std::getline(in,s)) {
ss.push(s);
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop(); }
this code works OK, but...
my log.txt file:
d/t: 2006-12-23/18:52:47 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe
and output file:
d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
2006-12-23/18:52:47 D:\c++\sem1\Project1.exe
where is my "d/t: " ?
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 wrote in message ...
>
ifstream in("log.txt");
ofstream out("out.txt");
stack<stringss;
string s;
in >s;
while (std::getline(in,s)) {
ss.push(s);
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop(); }
this code works OK, but...
my log.txt file:
d/t: 2006-12-23/18:52:47 D:\c++\sem1\Project1.exe d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe
and output file:
d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
2006-12-23/18:52:47 D:\c++\sem1\Project1.exe
where is my "d/t: " ?
string s;
in >s; // it's in this string you didn't save.
// delete that line.
while (std::getline(in,s)) { ss.push(s); }
--
Bob R
POVrookie
BobR napisał(a):
>where is my "d/t: " ?
string s;
in >s; // it's in this string you didn't save.
// delete that line.
while (std::getline(in,s)) { ss.push(s); }
works great!
thanks a lot!
--
Ground21____________\\
ground21@pocztaKROPKAfm
Ground21 ÐÉÓÁÌ(Á):
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)
Take it, i am slightly adapted it for C++ from C:
Declare in your program:
#include <stdio.h>
namespace NGround21
{
typedef unsigned int uint;
// store 'max_visible_chars' chars maximum to 'buf' and close by \0
//( ! ADD '\0' char to buf, total size can be 'max_visible_chars' +1
maximum )
// all 256 chars of DOS/Win/UNIX <EOLallowed
//special: to skip all chars till <EOLwrite:
getln(any_number,0,correct_pointer);
// "fi" must be open as "rb"
// return 0 if errors in parameters, else return !0
// "fi" file pointer will be after <EOLif return !0
char getln(char *const buf, const uint max_visible_chars, FILE
*const fi)throw();
//namespace NGround21
}
using namespace NGround21;
Write as separated cpp file, compile it and then link object file to
your project
#include <stdio.h>
char NGround21::getln(
char *const buf,
const uint max_visible_chars,
FILE *const fp
)throw()
{
if(
( (max_visible_chars) && (!buf) )
||( !fp )
)return 0;
char *p=buf;
for( uint len=0; ; )
{
int ch=fgetc(fp);
if( feof(fp) )break;
if( ch==13 )continue;
if( ch==10 )break;
if( len >= max_visible_chars )continue;
++len;
*p++=static_cast<char>(ch);
}
if( p ) *p=0;
return 1;
}
Oy, google makes error, look to the sorted list:
Building Compatible Libraries 11 ÎÏ×ÙÈ ÉÚ 11 Peter Olcott
(Á×ÔÏÒÙ: 4) 11 ñÎ×.
Simple program 20 Ground21 (Á×ÔÏÒÙ: 4) 18 äÅË. 2006
Read line after line but from the eof. 27 Ground21 (Á×ÔÏÒÙ:
8) 24 äÅË. 2006
Something Strange From the Days Way Before C++ 9 ÎÏ×ÙÈ ÉÚ 9
Tim Slattery (Á×ÔÏÒÙ: 7) 11 ñÎ×.
Possible causes for the 'delete ptr;' to core?? 7 ÎÏ×ÙÈ ÉÚ
7 Noah Roberts (Á×ÔÏÒÙ: 6) 11 ñÎ×.
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,
any efficient C++ / STL solution would be great
Thanks,
SK
On Jan 14, 3:17 pm, "Grizlyk" <grizl...@yandex.ruwrote:
Ground21 ÐÉÓÁÌ(Á):
Hello.
How could Ireadthe whole textfileline after line from the end of
file? (I want to ~copy~file)
Take it, i am slightly adapted it for C++ from C:
Declare in your program:
#include <stdio.h>
namespace NGround21
{
typedef unsigned int uint;
// store 'max_visible_chars' chars maximum to 'buf' and close by \0
//( ! ADD '\0' char to buf, total size can be 'max_visible_chars' +1
maximum )
// all 256 chars of DOS/Win/UNIX <EOLallowed
//special: to skip all chars till <EOLwrite:
getln(any_number,0,correct_pointer);
// "fi" must be open as "rb"
// return 0 if errors in parameters, else return !0
// "fi"filepointer will be after <EOLif return !0
char getln(char *const buf, const uint max_visible_chars,FILE
*const fi)throw();
//namespace NGround21}
using namespace NGround21;
Write as separated cppfile, compile it and then link objectfileto
your project
#include <stdio.h>
char NGround21::getln(
char *const buf,
const uint max_visible_chars,
FILE*const fp
)throw()
{
if(
( (max_visible_chars) && (!buf) )
||( !fp )
)return 0;
char *p=buf;
for( uint len=0; ; )
{
int ch=fgetc(fp);
if( feof(fp) )break;
if( ch==13 )continue;
if( ch==10 )break;
if( len >= max_visible_chars )continue;
++len;
*p++=static_cast<char>(ch);
}
if( p ) *p=0;
return 1;
}- Hide quoted text -
- Show quoted text -
On 26 Feb, 14:52, "SKumar" <SureshKumar...@gmail.comwrote:
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,
any efficient C++ / STL solution would be great
If its too big for memory. Read as many as you can to the stack.
when attempting to push stack throws bad_alloc pop all the stack to a
unique name temp file. (You need to take care to not lose the last bit
of input data of course, but the stack contents that succeeded should
not be violated)
save the unique temp filenames on another stack.
then start again reading data, starting with the last bit of data that
failed.
when the input is done pop the filename stack one by one and read the
resulting files to your output file.
To speed things up you could preallocate a big chunk in your stack
container. You would probably need to experiment to find how much
memory you can grab, just keep catching exceptions and reducing the
size.
Untested .... ;-)
regards
Andy Little
On 26 Feb, 17:31, "kwikius" <a...@servocomm.freeserve.co.ukwrote:
On 26 Feb, 14:52, "SKumar" <SureshKumar...@gmail.comwrote:
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,
any efficient C++ / STL solution would be great
If its too big for memory. Read as many as you can to the stack.
when attempting to push stack throws bad_alloc pop all the stack to a
unique name temp file. (You need to take care to not lose the last bit
of input data of course, but the stack contents that succeeded should
not be violated)
save the unique temp filenames on another stack.
then start again reading data, starting with the last bit of data that
failed.
when the input is done pop the filename stack one by one and read the
resulting files to your output file.
To speed things up you could preallocate a big chunk in your stack
container. You would probably need to experiment to find how much
memory you can grab, just keep catching exceptions and reducing the
size.
Untested .... ;-)
regards
Andy Little
There is a fatal flaw in this scheme, which is that when you try to
push your filename stack you will probably get bad_alloc too. Youre
all out of memory :-)
You will need to find a way to give the system some memory back when
required, or try a less agressive approach to the whole thing ;-)
regards
Andy Little This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Chuck Anderson |
last post by:
Can anyone point me in the right direction? I want to use Php to
automate confirmation of someone joining an email list by them replying
to an email (so they don't have to have a browser?).
I...
|
by: hvaisane |
last post by:
Valgrind says
==11604== Invalid read of size 4
==11604== at 0x8048ABB: main (foo.cc:36)
==11604== Address 0x1B92415C is 4 bytes inside a block of size 8 free'd
==11604== at 0x1B90514F:...
|
by: jas |
last post by:
Hi,
I would like to start a new process and be able to read/write from/to
it. I have tried things like...
import subprocess as sp
p = sp.Popen("cmd.exe", stdout=sp.PIPE)...
|
by: ESPN Lover |
last post by:
Below is two snippets of code from MSDN showing how to read a file. Is one
way preferred over the other and why? Thanks.
using System;
using System.IO;
class Test
{
public static void...
|
by: oncelovecoffee |
last post by:
str_Array() 'strings
I need save it to file and next time i can read from file.
--------------------------------------------------------...
|
by: Samuel M. Smith |
last post by:
I have been playing around with a subclass of dict wrt a recipe for
setting dict items using attribute syntax.
The dict class has some read only attributes that generate an
exception if I try to...
|
by: waffle.horn |
last post by:
Hi,
if this makes sense i want to create a function that can be called so
that it reads a single line from a file, then after using the
information destroys it. Such that when the function is...
|
by: flebber |
last post by:
I was working at creating a simple program that would read the content
of a playlist file( in this case *.k3b") and write it out . the
compressed "*.k3b" file has two file and the one I was trying...
|
by: arnuld |
last post by:
This works fine, I welcome any views/advices/coding-practices :)
/* C++ Primer - 4/e
*
* Exercise 8.9
* STATEMENT:
* write a program to store each line from a file into a
*...
|
by: Sean Davis |
last post by:
I have a large file that I would like to transform and then feed to a
function (psycopg2 copy_from) that expects a file-like object (needs
read and readline methods).
I have a class like so:
...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
| |